home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / CRS / crs49.d81 / hack6b.sfx / issue6b
Text File  |  1990-02-12  |  58KB  |  1,607 lines

  1. =============================================================================
  2. ╠┌╫ ├OMPRESSION
  3. BY ┬ILL ╠UCIER (┬LUCIER@ERSYS.EDMONTON.AB.CA, B.LUCIER1 ON ╟ENIE)
  4.  
  5. ╠┌╫ IS PERHAPS THE MOST WIDELY USED FORM OF DATA COMPRESSION TODAY. ╔T
  6. IS SIMPLE TO IMPLEMENT AND ACHIEVES VERY DECENT COMPRESSION AT A FAIRLY
  7. QUICK PACE. ╠┌╫ IS USED IN ╨╦┌╔╨ (SHRINK),╨╦┴╥├ (CRUNCH), GIFS,╓.42BIS
  8. AND UNIX'S COMPRESS. ╘HIS ARTICLE WILL ATTEMPT TO EXPLAIN HOW THE
  9. COMPRESSION WORKS WITH A SHORT EXAMPLE AND 6502 SOURCE CODE IN ┬UDDY
  10. FORMAT.
  11.  
  12. ╧RIGINALLY NAMED LZ78, IT WAS INVENTED BY ╩ACOB ┌IV AND ┴BRAHAM ╠EMPEL
  13. IN 1978 , IT WAS LATER MODIFIED BY ╘ERRY ╫ELCH TO ITS PRESENT FORMAT.
  14. ╘HE PATENT FOR THE ╠┌╫ COMPRESSION METHOD IS PRESENTLY HELD BY ╒NISYS.
  15.  
  16. ╠┌╫ COMPRESSES DATA BY TAKING PHRASES AND COMPRESSING THEM INTO CODES.
  17. ╘HE SIZE OF THE CODES COULD VARY FROM 9 BITS TO 16 BITS. ┴LTHOUGH FOR
  18. THIS IMPLEMENTATION WE WILL BE USING ONLY 12 BITS. ┴S BYTE ARE READ IN
  19. FROM A FILE THEY ARE ADDED TO A DICTIONARY. ╞OR A 12-BIT IMPLEMENTATION
  20. A DICTIONARY WILL BE 4K (2^12=4096) . ┼ACH ENTRY IN THE DICTIONARY
  21. REQUIRES FIVE BYTES, WHICH WILL BE BUILT IN THE FORM OF A TREE. ╔T IS
  22. NOT A BINARY TREE BECAUSE EACH NODE MAY HAVE MORE THAN TWO OFFSPRINGS.
  23. ╔N FACT, BECAUSE OUR DICTIONARY CAN HOLD UP TO 4096 DIFFERENT CODES IT
  24. IS POSSIBLE TO HAVE ONE NODE WITH 3800 CHILDREN NODES, ALTHOUGH THIS IS
  25. NOT LIKELY TO HAPPEN. ╘HE FIVE BYTES THAT MAKE UP OUR TREE WILL BE:
  26.  
  27. ╘HE PARENT CODE: ┼ACH NODE HAS ONE AND ONLY ONE PARENT NODE. ╫HEN THE PARENT
  28.                  CODE IS LESS THEN 255 IT IS THE END OF A PHRASE. ╘HE CODES
  29.                  0-255 DO NOT ACTUALLY EXIST IN THE TREE. ╘HE FOLLOWING
  30.                  VALUES DO NOT APPEAR EITHER AS THEY HAVE SPECIAL MEANING:
  31.  
  32.                  256 : ┼ND OF ╙TREAM-╘HIS MARKS THE END OF ONE COMPRESSED FILE
  33.                  257 : ╘HIS TELLS THE DECOMPRESSOR TO INCREASE THE NUMBER
  34.                        OF BITS ITS READING BY ONE.
  35.                  258 : ╫IPE OUT DICTIONARY
  36.                  
  37. ╘HE CODE VALUE : ╘HIS IS THE CODE THAT WILL BE SENT TO THE COMPRESSOR. 
  38. ╘HE CHARACTER  : ╘HE VALUE CONTAINED AT THIS NODE. ╔T HAVE A VALUE OF 0-255.
  39.  
  40. ╔NITIALLY WE SEND OUT CODES THAT ARE 9 BITS LONG, THIS WILL COVER THE VALUES
  41. 0-511. ╧NCE WE HAVE REACHED 511, WE WILL NEED TO INCREASE THE NUMBER OF
  42. BITS TO WRITE BY 1. ╘HIS WILL GIVE ROOM FOR CODE NUMBERS 512-1023, OR
  43. (2^10)-1. ┴T THIS POINT WE MUST ENSURE THAT THE DECOMPRESSOR KNOWS HOW
  44. BITS TO READ IN AT ONCE SO A CODE NUMBER 257 IS SENT TO INDICATE THAT
  45. THE NUMBER OF BITS TO BE READ IS TO BE BUMPED UP BY ONE. ╘HE SIZE OF THE
  46. DICTIONARY IS FINITE SO AT SOME POINT WE DO HAVE TO BE CONCERNED WITH
  47. WHAT WE WILL DO WHEN IT DOES FILL UP. ╫E COULD STOP COMPILING NEW
  48. PHRASES AND JUST COMPRESS WITH THE ONES THAT ARE ALREADY IN THE
  49. DICTIONARY. ╘HIS IS NOT A VERY GOOD CHOICE, FILES TEND TO CHANGE
  50. FREQUENTLY (EG. PROGRAM FILES AS THEY CHANGE FROM CODE TO DATA) SO
  51. STICKING WITH THE SAME DICTIONARY WILL ACTUALLY INCREASE THE SIZE OF THE
  52. FILE OR AT BEST, GIVE POOR COMPRESSION. ┴NOTHER CHOICE IS TO WIPE THE
  53. DICTIONARY OUT AND START BUILDING NEW CODES AND PHRASES, OR WIPE OUT
  54. SOME OF THE DICTIONARY LEAVING BEHIND ONLY THE NEWER CODES AND PHRASES.
  55. ╞OR THE SAKE OF SIMPLICITY THIS PROGRAM WILL JUST WIPE OUT THE
  56. DICTIONARY WHEN IT BECOMES FULL.
  57.  
  58. ╘O ILLUSTRATE HOW ╠┌╫ WORKS A SMALL PHRASE WILL BE COMPRESSED : HEHER.
  59. ╘O START THE FIRST TWO CHARACTERS WOULD BE READ IN. ╘HE ╚ WOULD BE
  60. TREATED AS THE PARENT CODE AND ┼ BECOMES THE CHARACTER CODE. ┬Y MEANS OF
  61. A HASHING ROUTINE (THE HASHING ROUTINE WILL BE EXPLAINED MORE FULLY IN
  62. THE SOURCE CODE) THE LOCATION WHERE ╚┼ SHOULD BE IS LOCATED. ╙INCE WE
  63. HAVE JUST BEGUN THERE WILL BE NOTHING THERE,SO THE PHRASE WILL BE ADDED
  64. TO THE DICTIONARY. ╘HE CODES 0-258 ARE ALREADY TAKEN SO WE START USING
  65. 259 AS OUR FIRST CODE. ╘HE BINARY TREE WOULD LOOK SOMETHING LIKE THIS:
  66.             
  67.           NODE # 72 - ╚
  68.                  ▄
  69.      NODE #3200 259 - ┼
  70.  
  71.  ╘HE NODE # FOR ┼ IS AN ARBITRARY ONE. ╘HE COMPRESSOR MAY NOT CHOOSE
  72. THAT LOCATION, 3200 IS USED STRICTLY FOR DEMONSTRATION PURPOSES. ╙O AT
  73. NODE #3200 THE VALUES WOULD BE:
  74.  
  75. ╨ARENT CODE - 72
  76. CODE VALUE  - 259
  77. CHARACTER   - ┼
  78.  
  79. ╘HE NODE #72 IS NOT ACTUALLY USED. ┴S SOON AS A VALUE LESS THAN 255 IS
  80. FOUND IT IS ASSUMED TO BE THE ACTUAL VALUE. ╫E CAN'T COMPRESS THIS YET
  81. SO THE VALUE 72 IS SENT TO THE OUTPUT FILE(REMEMBER THAT IT IS SENT IN 9
  82. BITS). ╘HE ┼ THEN BECOMES THE PARENT CODE AND A NEW CHARACTER CODE ( ╚ )
  83. IS READ IN. ┴FTER AGAIN SEARCHING THE DICTIONARY THE PHRASE ┼╚ IS NOT
  84. FOUND. ╔T IS ADDED TO THE DICTIONARY AS CODE NUMBER 260. ╘HEN WE SEND
  85. THE ┼ TO THE DISK AND ╚ BECOMES THE NEW PARENT CODE AND THE NEXT ┼
  86. BECOMES THE NEW CHARACTER CODE. ┴FTER SEARCHING THE DICTIONARY WE FIND
  87. THAT WE CAN COMPRESS ╚┼ INTO THE CODE 259,WE WANT TO COMPRESS AS MUCH AS
  88. POSSIBLE INTO ONE CODE SO WE MAKE 259 THE PARENT CODE. ╘HERE MAY BE A
  89. LONGER STRING THEN ╚┼ THAT CAN BE COMPRESSED. ╘HE ╥ IS READ IN AS THE
  90. NEW CHARACTER CODE. ╘HE DICTIONARY IS SEARCHED FOR THE A 259 FOLLOWED A
  91. ╥, SINCE IT IS NOT FOUND IT IS ADDED TO THE DICTIOARY AND IT LOOKS LIKE
  92. THIS:
  93.  
  94.            NODE #72 - ╚             NODE #69 - ┼
  95.                  ▄                        ▄ 
  96.     NODE #3200  259 - ┼    NODE #1600    260 - ╚
  97.                  ▄
  98.     NODE #1262  261 - ╥
  99.  
  100. ╘HEN THE VALUE 259 IS SENT TO THE OUTPUT FILE (TO REPRESENT THE ╚┼) AND
  101. SINCE THAT IS THE ┼╧╞ THE ╥ IS SENT AS WELL,AS WELL AS A 256 TO INDICATE
  102. THE ┼╧╞ HAS BEEN REACHED.
  103.  
  104. ─ECOMPRESSION IS EXTREMELY SIMPLE. ┴S LONG AS THE DECOMPRESSOR MAINTAINS
  105. THE DICTIONARY AS THE COMPRESSOR DID, THERE WILL BE NO PROBLEMS,EXCEPT
  106. FOR ONE PROBLEM THAT CAN BE HANDLED AS AN EXCEPTIONAL CASE. ┴LL OF THE
  107. LITTLE DETAILS OF INCREASING THE NUMBER OF BITS TO READ, AND WHEN TO
  108. FLUSH THE DICTIONARY ARE TAKEN CARE OF BY THE COMPRESSOR. ╙O IF THE
  109. DICTIONARY WAS INCREASED TO 8K, THE COMPRESSOR WOULD HAVE TO BE SET UP
  110. TO HANDLE A LARGER DICTIONARY, BUT THE DECOMPRESSOR ONLY DOES AS THE
  111. COMPRESSED FILE TELLS IT TO AND WILL WORK WITH ANY SIZE DICTIONARY. ╘HE
  112. ONLY PROBLEM WOULD BE THAT A LARGER DICTIONARY WILL CREEP INTO THE RAM
  113. UNDER THE ROM OR POSSIBLY EVEN USE ALL AVAILABLE MEMORY, BUT ASSUMING
  114. THAT THE RAM IS AVAILABLE THE DECOMPRESSOR WILL NOT CHANGE. ╘HE
  115. DECOMPRESSOR WOULD START OUT READING 9 BITS AT A TIME, AND STARTS IT
  116. FREE CODE AT 259 AS THE COMPRESSOR DID. ╘O USE THE ABOVE INPUT FROM THE
  117. COMPRESSOR AS AN EXAMPLE, THE OUTPUT WAS:
  118.  
  119. 72  - ╞OR THE ╞IRST ╚
  120. 69  - ╞OR THE ╞IRST ┼
  121. 259 - ╞OR THE ├OMPRESSED ╚┼
  122. 82  - ╞OR THE ╥
  123. 256 - ┼OF INDICATOR
  124.  
  125.  ╘O BEGIN DECOMPRESSING, TWO VALUES ARE NEEDED. ╘HE ╚ AND ┼ ARE READ IN,
  126. (NOTE THEY WILL BOTH BE 9 BITS LONG). ┴S THEY ARE BOTH BELOW 256 THEY
  127. ARE AT THE END OF THE STRING AND ARE SENT STRAIGHT TO THE OUTPUT FILE.
  128. ╘HE FIRST FREE CODE IS 259 SO THAT IS THE VALUE ASSIGNED TO THE PHRASE
  129. ╚┼. ╬OTE WHEN DECOMPRESSING THERE IS NO NEED FOR THE HASHING ROUTINE,
  130. THE CODES ARE THE ABSOLUTE LOCATIONS IN THE DICTIONARY (I.E. ╔F THE
  131. DICTIONARY WAS CONSIDERED TO BE AN ARRAY THEN THE ENTRY NUMBER 259 WOULD
  132. BE DICTIONARY[259]), BECAUSE OF THIS, THE CODE VALUE IS NO LONGER
  133. NEEDED. ╙O THE DECOMPRESSOR WOULD HAVE AN ENTRY THAT LOOKS LIKE THIS:
  134.  
  135. ╬ODE # 259
  136. ╨ARENT ├ODE - ╚
  137. ├HARACTER   - ┼
  138.  
  139. ╘HE DECOMPRESSOR WILL READ IN THE NEXT VALUE (259). ┬ECAUSE THE NODE
  140. NUMBER IS AT THE END OF THE COMPRESSED STRING WE WILL HAVE TO TAKE THE
  141. CODE VALUE AND PLACE IT ON A STACK, AND TAKE THEM OFF IN A
  142. ╠AST-IN,╞IRST-OUT (╠╔╞╧) FASHION. ╘HAT IS TO SAY THAT THE FIRST
  143. CHARACTER TO GO ON THE STACK (IN THIS CASE THE ┼) WILL BE THE LAST TO
  144. COME OFF. ╘HE SIZE OF THE STACK IS DEPENDENT ON THE SIZE OF THE
  145. DICTIONARY, SO FOR THIS IMPLEMENTATION WE NEED A STACK THAT IS 4K LONG.
  146. ┴FTER ALL THE CHARACTERS FROM THE STRING HAVE BEEN PLACED ON THE STACK
  147. THEY ARE TAKEN OFF AND SENT TO THE OUTPUTFILE.
  148.  
  149.   ╘HERE IS ONE SMALL ERROR THAT IS POSSIBLE WITH ╠┌╫ BECAUSE OF THE WAY
  150. THE COMPRESSOR DEFINES STRINGS. ├ONSIDER THE COMPRESSION DICTIONARY THAT
  151. HAS THE FOLLOWING IN IT:
  152.  
  153.      NODE #   ├ODE         ╨ARENT  CHARACTER 
  154.               ╓ALUE         CODE 
  155.      ------   ------        ------  ---------
  156.         65      65           N/A       ┴ 
  157.        723     259            65       ├
  158.       1262     260           259       ╒
  159.       2104     261           260       ╘
  160.       2506     262           261       ┼
  161.  
  162. ╬OW IF THE COMPRESSOR WAS TO TRY TO COMPRESS THE STRING ┴├╒╘┼┴├╒╘┼┴ ╘HE
  163. COMPRESSOR WILL FIND A MATCH FOR THE FIRST FIVE CHARACTERS '┴├╒╘┼' AND
  164. WILL SEND A 262 TO THE OUTPUT FILE. ╘HEN IT WILL ADD THE FOLLOWING ENTRY
  165. TO THE DICTIONARY:
  166.  
  167.       3099     263           262       ┴
  168.  
  169. ╬OW IT WILL TRY TO COMPRESS THE REMAINING CHARACTERS, AND IT FINDS THAT
  170. IT CAN COMPRESS THE ENTIRE STRING WITH THE CODE 263, BUT NOTICE THAT THE
  171. MIDDLE ┴, THE ONE THAT WAS JUST ADDED ONTO THE END OF THE STRING '┴├╒╘┼'
  172. WAS NEVER SENT TO THE OUTPUT FILE. ╘HE DECOMPRESSOR WILL NOT HAVE THE
  173. CODE 263 DEFINED IN IT'S DICTIONARY. ╘HE LAST CODE IT WILL HAVE DEFINED
  174. WILL BE 262. ╘HIS PROBLEM IS EASILY REMEDIED THOUGH, WHEN THE
  175. DECOMPRESSOR DOES NOT HAVE A CODE DEFINED, IT TAKES THE FIRST LETTER
  176. FROM THE LAST PHRASE DEFINED AND TACKS IT ONTO THE END OF THE LAST
  177. PHRASE. ╔┼ ╔T TAKES THE FIRST LETTER (THE ┴) FROM THE PHRASE AND ADDS IT
  178. ON TO THE END AS CODE #263.
  179.  
  180. ╘HIS PARTICULAR IMPLEMENTATION IS FAIRLY SLOW BECAUSE IT READS A BYTE
  181. AND THEN WRITES ONE, IT COULD BE MADE MUCH FASTER WITH SOME BUFFERING.
  182. ╔T IS ALSO LIMITED TO COMPRESSING AND DECOMPRESSING ONE FILE AT A TIME
  183. AND HAS NO ERROR CHECKING CAPABILITIES. ╔T IS MEANT STRICTLY TO TEACH
  184. ╠┌╫ COMPRESSION, NOT PROVIDE A FULL FLEDGED COMPRESSOR.
  185.  
  186. ┴ND NOW FOR THE CODE:
  187.   
  188. ╙┘╙ 4000      ; SYS 999 ON A 64
  189. .─╓╧ 9        ; OR WHATEVER DRIVE USED FOR OUTPUT
  190. .╧╥╟ 2500
  191. .╧┬╩ "╠┌╫.═╠"
  192.  
  193. ╘┴┬╠┼╙╔┌┼ =5021     
  194.  
  195. ; ╘╚┼ ╘┴┬╠┼╙╔┌┼ ╔╙ ┴├╘╒┴╠╠┘ 5021, ┴┬╧╒╘ 20% ╠┴╥╟┼╥ ╘╚┼╬ 4╦. ╘╚╔╙ ╟╔╓┼╙
  196. ; ╘╚┼ ╚┴╙╚╔╬╟ ╥╧╒╘╔╬┼ ╙╧═┼ ╥╧╧═ ╘╧ ═╧╓┼. ╔╞ ╘╚┼ ╘┴┬╠┼ ╫┴╙ ┼╪┴├╘╠┘ 4╦
  197. ; ╘╚┼╥┼ ╫╧╒╠─ ┬┼ ╞╥┼╤╒┼╬╘ ├╧╠╠╔╙╔╧╬╙ ╫╚┼╥┼ ─╔╞╞┼╥┼╬╘ ├╧═┬╔╬┴╘╔╧╬╙ ╧╞
  198. ; ├╚┴╥┴├╘┼╥╙ ╫╧╒╠─ ╚┴╓┼ ╘╚┼ ╙┴═┼ ╚┴╙╚ ┴──╥┼╙╙. ╔╬├╥┼┴╙╔╬╟ ╘╚┼ ╘┴┬╠┼ ╙╔┌┼
  199. ; ╥┼─╒├┼╙ ╘╚┼ ╬╒═┬┼╥ ╧╞ ├╧╠╠╔╙╔╧╬╙.
  200.  
  201. ┼╧╙ =256          ; EOS = ┼ND OF STREAM ╘HIS MARKS THE END OF FILE
  202.  
  203. ╞╔╥╙╘├╧─┼ =259
  204. ═┴╪├╧─┼ =4096
  205.  
  206. ┬╒═╨├╧─┼ =257     ; ╫HENEVER A 257 IS ENCOUNTERED BY THE DECOMPRESSOR IT
  207.                   ; INCREASES THE NUMBER OF BITS IT READS BY 1
  208.  
  209. ╞╠╒╙╚├╧─┼ =258   
  210.  
  211. ╘┴┬╠┼┬┴╙┼ =14336  ; ╘HE LOCATION THAT THE DICTIONARY IS LOCATED AT
  212.  
  213. ─┼├╧─┼╙╘┴├╦ =9300 ; ╘HE LOCATION OF THE 4K ╠╔╞╧ STACK
  214.  
  215. ; ╧╥╟ = ─┼├╧═╨╥┼╙╙ ╞╔╠┼
  216. ; ╧╥╟ + 3 = ├╧═╨╥┼╙╙ ╞╔╠┼
  217.  
  218. ╩═╨ ┼╪╨┴╬─╞╔╠┼
  219.  
  220. ;********************************
  221. ; ├╧═╨╥┼╙╙╞╔╠┼
  222. ;********************************
  223.  
  224. ├╧═╨╥┼╙╙╞╔╠┼ ╩╙╥ ╔╬╔╘─╔├ ; ┼═╨╘┘ ╘╚┼ ─╔├╘╔╧╬┴╥┘
  225. ╠─┴ #128
  226. ╙╘┴ ┬╔╘═┴╙╦
  227. ╠─┴ #0
  228. ╙╘┴ ╥┴├╦
  229. ╩╙╥ ╟┼╘├╚┴╥      ; ╟┼╘ ┴ ├╚┴╥ ╞╥╧═ ╘╚┼ ╔╬╨╒╘ ╞╔╠┼
  230. ╙╘┴ ╙╘╥╔╬╟├╧─┼   ; ╔╬╔╘╔┴╠╔┌┼ ╘╚┼ ╙╘╥╔╬╟├╧─┼ (╨┴╥┼╬╘ ├╧─┼)
  231. ╠─┴ #0
  232. ╙╘┴ ╙╘╥╔╬╟├╧─┼+1
  233. ╬┼╪╘├╚┴╥ ╩╙╥ ╟┼╘├╚┴╥
  234.          ╙╘┴ ├╚┴╥┴├╘┼╥
  235.          ╩╙╥ ╞╔╬─╬╧─┼    ; ╞╔╬─╬╧─┼ ├┴╠├╒╠┴╘┼╙ ╘╚┼ ╚┴╙╚┼─ ╠╧├┴╘╔╧╬ ╧╞
  236.          ╠─┴ ($╞┼),┘     ; ╘╚┼ ╙╘╥╔╬╟├╧─┼ ┴╬─ ├╚┴╥┴├╘┼╥  ╔╬ ╘╚┼ ─╔├╘.
  237.          ╔╬┘             ; ┴╬─ ╙┼╘╙ $╞┼/$╞╞ ╨╧╔╬╘╔╬╟ ╘╧ ╔╘. ╔╞ ╘╚┼ ┼╬╘╥┘
  238.          ┴╬─ ($╞┼),┘     ; ╚┴╙ ╘╫╧ 255 ╔╬ ╔╘ ╘╚┼╬ ╔╘ ╔╙ ┼═╨╘┘ ┴╬─ ╙╚╧╒╠─
  239.          ├═╨ #255        ; ┬┼ ┴──┼─ ╘╧ ╘╚┼ ─╔├╘╔╧╬┴╥┘.
  240.          ┬┼╤ ┴──╘╧─╔├╘
  241.              ╠─┴ ($╞┼),┘     ; ╔╘ ╚┴╙ ┴ ─┼╞╔╬┼─ ╨╚╥┴╙┼. ╙╘╧╥┼ ╘╚┼ ├╧─┼ ╓┴╠╒┼ ╔╬
  242.              ╙╘┴ ╙╘╥╔╬╟├╧─┼+1; ╘╚┼ ╨┴╥┼╬╘ ├╧─┼
  243.              ─┼┘
  244.              ╠─┴ ($╞┼),┘
  245.              ╙╘┴ ╙╘╥╔╬╟├╧─┼
  246.          ╩═╨ ┼╧╞
  247.          ┴──╘╧─╔├╘ ╠─┘ #0
  248.          - ╠─┴ ╬┼╪╘├╧─┼,┘
  249.            ╙╘┴ ($╞┼),┘
  250.            ╔╬┘
  251.            ├╨┘ #5
  252.          ┬╬┼ -
  253.          ╔╬├ ╬┼╪╘├╧─┼             ; ╔╬├╥┼┴╙┼ ╘╚┼ ╬┼╪╘├╧─┼
  254.          ┬╬┼ +
  255.              ╔╬├ ╬┼╪╘├╧─┼+1
  256.          + ╩╙╥ ╧╒╘╨╒╘
  257.          ╠─┴ ╬┼╪╘├╧─┼+1          ; ├╚┼├╦ ╔╞ ╬┼╪╘├╧─┼=4096 ╔╞ ╙╧ ╘╚┼╬ ╞╠╒╙╚ ╘╚┼
  258.          ├═╨ #>═┴╪├╧─┼           ; ─╔├╘╔╧╬┴╥┘ ┴╬─ ╙╘┴╥╘ ┴╬┼╫
  259.          ┬╬┼ ├╚┼├╦┬╒═╨
  260.          ╠─┴ ╬┼╪╘├╧─┼
  261.          ├═╨ #<═┴╪├╧─┼
  262.          ┬╬┼ ├╚┼├╦┬╒═╨
  263.          ╠─┴ #<╞╠╒╙╚├╧─┼        ; ╙┼╬─ ╘╚┼ ╞╠╒╙╚ ├╧─┼ ╘╧ ╘╚┼ ├╧═╨╥┼╙╙┼─ ╞╔╠┼ ╙╧
  264.          ╙╘┴ ╙╘╥╔╬╟├╧─┼         ; ╘╚┼ ─┼├╧═╨╥┼╙╙╧╥ ╫╔╠╠ ╦╬╧╫ ╘╧ ╞╠╒╙╚ ╘╚┼
  265.          ╠─┴ #>╞╠╒╙╚├╧─┼        ; ─╔├╘╔╧╬┴╥┘
  266.          ╙╘┴ ╙╘╥╔╬╟├╧─┼+1
  267.          ╩╙╥ ╧╒╘╨╒╘
  268.          ╩╙╥ ╔╬╔╘─╔├
  269.          ╩═╨ ├╚┼├╦┼╧╞
  270.          ├╚┼├╦┬╒═╨ ╠─┴ ╬┼╪╘┬╒═╨+1
  271.          ├═╨ ╬┼╪╘├╧─┼+1         ; ├╚┼├╦┬╒═╨ ├╚┼├╦ ╘╧ ╙┼┼ ╔╞ ╘╚┼ ╬┼╪╘├╧─┼ ╚┴╙
  272.          ┬╬┼ ├╚┼├╦┼╧╞        ; ╥┼┴├╚┼─ ╘╚┼ ═┴╪╔═╒═ ╓┴╠╒┼ ╞╧╥ ╘╚┼ ├╒╥╥┼╬╘
  273.          ╠─┴ ╬┼╪╘┬╒═╨                    ; ╬╒═┬┼╥ ╧╞ ┬╔╘╙ ┬┼╔╬╟ ╧╒╘╨╒╘.
  274.          ├═╨ ╬┼╪╘├╧─┼        ; ╞╧╥     ╪  ┬╔╘╙     ╬┼╪╘├╧─┼ ╚┴╙ ┘ ╨╚╥┴╙┼╙
  275.          ┬╬┼ ├╚┼├╦┼╧╞        ;        --------     -----------------------
  276.          ╠─┴ #>┬╒═╨├╧─┼      ;           9                 511
  277.          ╙╘┴ ╙╘╥╔╬╟├╧─┼+1    ;          10                1023
  278.          ╠─┴ #<┬╒═╨├╧─┼      ;          11                2047
  279.          ╙╘┴ ╙╘╥╔╬╟├╧─┼      ;          12                4095
  280.          ╩╙╥ ╧╒╘╨╒╘
  281.          ╔╬├ ├╒╥╥┼╬╘┬╔╘╙
  282.          ┴╙╠ ╬┼╪╘┬╒═╨
  283.          ╥╧╠ ╬┼╪╘┬╒═╨+1
  284.          ├╚┼├╦┼╧╞ ╠─┴ #0
  285.          ╙╘┴ ╙╘╥╔╬╟├╧─┼+1
  286.          ╠─┴ ├╚┴╥┴├╘┼╥
  287.          ╙╘┴ ╙╘╥╔╬╟├╧─┼
  288.          ┼╧╞ ╠─┴ 144
  289.          ┬╬┼ ─╧╬┼
  290. ╩═╨ ╬┼╪╘├╚┴╥
  291. ─╧╬┼ ╩╙╥ ╧╒╘╨╒╘
  292. ╠─┴ #>┼╧╙               ; ╙┼╬─ ┴ 256 ╘╧ ╔╬─╔├┴╘┼ ┼╧╞
  293. ╙╘┴ ╙╘╥╔╬╟├╧─┼+1
  294. ╠─┴ #<┼╧╙
  295. ╙╘┴ ╙╘╥╔╬╟├╧─┼
  296. ╩╙╥ ╧╒╘╨╒╘
  297. ╠─┴ ┬╔╘═┴╙╦
  298. ┬┼╤ +
  299.     ╩╙╥ $╞╞├├
  300.     ╠─╪ #3
  301.     ╩╙╥ $╞╞├9
  302.     ╠─┴ ╥┴├╦              ; ╙┼╬─ ╫╚┴╘ ┬╔╘╙ ╫┼╥┼╬'╘ ╙┼╬─ ╫╚┼╬ ╧╒╘╨╒╘
  303.     ╩╙╥ $╞╞─2
  304. + ╩╙╥ $╞╞├├
  305. ╠─┴ #3
  306. ╩╙╥ $╞╞├3
  307. ╠─┴ #2
  308. ╩═╨ $╞╞├3
  309.  
  310. ;**********************************
  311. ; ╔╬╔╘─╔├
  312. ; ╔╬╔╘╔┴╠╔┌┼╙ ╘╚┼ ─╔├╘╔╧╬┴╥┘, ╙┼╘╙
  313. ; ╘╚┼ ╬╒═┬┼╥ ╧╞ ┬╔╘╙ ╘╧ 9
  314. ;**********************************
  315.  
  316. ╔╬╔╘─╔├ ╠─┴ #9
  317. ╙╘┴ ├╒╥╥┼╬╘┬╔╘╙
  318. ╠─┴ #>╞╔╥╙╘├╧─┼
  319. ╙╘┴ ╬┼╪╘├╧─┼+1
  320. ╠─┴ #<╞╔╥╙╘├╧─┼
  321. ╙╘┴ ╬┼╪╘├╧─┼
  322. ╠─┴ #>512
  323. ╙╘┴ ╬┼╪╘┬╒═╨+1
  324. ╠─┴ #<512
  325. ╙╘┴ ╬┼╪╘┬╒═╨
  326. ╠─┴ #<╘┴┬╠┼┬┴╙┼
  327. ╙╘┴ $╞┼
  328. ╠─┴ #>╘┴┬╠┼┬┴╙┼
  329. ╙╘┴ $╞╞
  330. ╠─┴ #<╘┴┬╠┼╙╔┌┼
  331. ╙╘┴ $╞├
  332. ╠─┴ #>╘┴┬╠┼╙╔┌┼
  333. ╙╘┴ $╞─
  334. - ╠─┘ #0
  335.   ╠─┴ #255      ; ┴╠╠ ╘╚┼ ├╧─┼ ╓┴╠╒┼╙ ┴╥┼ ╔╬╔╘ ╘╧ 255+256*255
  336.   ╙╘┴ ($╞┼),┘   ; ╧╥ -1 ╔╬ ╘╫╧ ├╧═╨╠┼═┼╬╘
  337.   ╔╬┘
  338.   ╙╘┴ ($╞┼),┘
  339.   ├╠├
  340.   ╠─┴ #5        ; ┼┴├╚ ┼╬╘╥┘ ╔╬ ╘╚┼ ╘┴┬╠┼ ╘┴╦┼╙ 5 ┬┘╘┼╙
  341.   ┴─├ $╞┼
  342.   ╙╘┴ $╞┼
  343.   ┬├├ +
  344.       ╔╬├ $╞╞
  345.   + ╠─┴ $╞├
  346.   ┬╬┼ +
  347.       ─┼├ $╞─
  348.   + ─┼├ $╞├
  349.   ╠─┴ $╞─
  350.   ╧╥┴ $╞├
  351. ┬╬┼ -
  352. ╥╘╙
  353.  
  354. ;************************************
  355. ; ╟┼╘├╚┴╥
  356. ;************************************
  357.  
  358. ╟┼╘├╚┴╥ ╩╙╥ $╞╞├├
  359. ╠─╪ #2
  360. ╩╙╥ $╞╞├6
  361. ╩═╨ $╞╞├╞
  362.  
  363. ;************************************
  364. ; ╧╒╘╨╒╘
  365. ;************************************
  366.  
  367. ╧╒╘╨╒╘ ╠─┴ #0      ; ╘╚┼ ╬╒═┬┼╥ ╧╞ ┬╔╘╙ ╧╒╘╨╒╘ ├┴╬ ┬┼ ╧╞ ┴ ╓┴╥╔┴┬╠┼
  368. ╙╘┴ ═┴╙╦+1         ; ╠┼╬╟╘╚,╙╧ ╘╚┼ ┬╔╘╙ ┴╥┼ ┴├├╒═╒╠┴╘┼─ ╘╧ ┴ ┬┘╘┼ ╔╙
  369. ╠─┴ #1             ; ╞╒╠╠ ┴╬─ ╘╚┼╬ ╔╘ ╔╙ ╙┼╬╘ ╘╧ ╘╚┼ ╧╒╘╨╒╘ ╞╔╠┼
  370. ╠─╪ ├╒╥╥┼╬╘┬╔╘╙
  371. ─┼╪
  372. - ┴╙╠
  373.   ╥╧╠ ═┴╙╦+1
  374.   ─┼╪
  375. ┬╬┼ -
  376. ╙╘┴ ═┴╙╦
  377. ═┴╙╦─╧╬┼ ╠─┴ ═┴╙╦
  378. ╧╥┴ ═┴╙╦+1
  379. ┬╬┼ +
  380.     ╥╘╙
  381. + ╠─┴ ═┴╙╦
  382. ┴╬─ ╙╘╥╔╬╟├╧─┼
  383. ╙╘┴ 3
  384. ╠─┴ ═┴╙╦+1
  385. ┴╬─ ╙╘╥╔╬╟├╧─┼+1
  386. ╧╥┴ 3
  387. ┬┼╤ ╬╧┬╔╘╧╬
  388.     ╠─┴ ╥┴├╦
  389.     ╧╥┴ ┬╔╘═┴╙╦
  390.     ╙╘┴ ╥┴├╦
  391. ╬╧┬╔╘╧╬ ╠╙╥ ┬╔╘═┴╙╦
  392. ╠─┴ ┬╔╘═┴╙╦
  393. ┬╬┼ +
  394.     ╩╙╥ $╞╞├├
  395.     ╠─╪ #3
  396.     ╩╙╥ $╞╞├9
  397.     ╠─┴ ╥┴├╦
  398.     ╩╙╥ $╞╞─2
  399.     ╠─┴ #0
  400.     ╙╘┴ ╥┴├╦
  401.     ╠─┴ #128
  402.     ╙╘┴ ┬╔╘═┴╙╦
  403. + ╠╙╥ ═┴╙╦+1
  404. ╥╧╥ ═┴╙╦
  405. ╩═╨ ═┴╙╦─╧╬┼
  406.  
  407. ;******************************
  408. ; ╞╔╬─╬╧─┼
  409. ; ╘╚╔╙ ╙┼┴╥├╚┼╙ ╘╚┼ ─╔├╘╔╧╬┴╥┘ ╘╔╠╠ ╔╘ ╞╔╬─╙ ┴ ╨┴╥┼╬╘ ╬╧─┼ ╘╚┴╘ ═┴╘├╚┼╙
  410. ; ╘╚┼ ╙╘╥╔╬╟├╧─┼ ┴╬─ ┴ ├╚╔╠─ ╬╧─┼ ╘╚┴╘ ═┴╘├╚┼╙ ╘╚┼ ├╚┴╥┴├╘┼╥ ╧╥ ┴ ┼═╨╘┘
  411. ; ╬╧─┼.
  412. ;*******************************
  413.  
  414. ; ╘╚┼ ╚┴╙╚╔╬╟ ╞╒╬├╘╔╧╬ - ╘╚┼ ╚┴╙╚╔╬╟ ╞╒╬├╘╔╧╬ ╔╙ ╬┼┼─┼─ ┬┼├┴╒╙┼
  415. ; ╘╚┼╥┼ ┴╥┼ 4096 ╪ 4096 (16 ═╔╠╠╔╧╬) ─╔╞╞┼╥┼╬╘ ├╧═┬╔╬┴╘╔╧╬╙ ╧╞
  416. ; ├╚┴╥┴├╘┼╥ ┴╬─ ╙╘╥╔╬╟├╧─┼. ┬┘ ═╒╠╘╔╨╠┘╔╬╟ ╘╚┼ ├╚┴╥┴├╘┼╥ ┴╬─ ╙╘╥╔╬╟├╧─┼
  417. ; ╔╬ ┴ ╞╧╥═╒╠┴ ╫┼ ├┴╬ ─┼╓┼╠╧╨ ╧╞ ═┼╘╚╧─ ╧╞ ╞╔╬─╔╬╟ ╘╚┼═ ╔╬ ╘╚┼
  418. ; ─╔├╘╔╧╬┴╥┘. ╔╞ ╘╚┼ ╙╘╥╔╬╟├╧─┼ ┴╬─ ├╚┴╥┴├╘┼╥ ╔╬ ╘╚┼ ─╔├╘╔╧╬┴╥┘
  419. ; ─╧╬'╘ ═┴╘├╚ ╘╚┼ ╧╬┼╙ ╫┼ ┴╥┼ ╠╧╧╦╔╬╟ ╞╧╥ ╫┼ ├┴╠├╒╠┴╘┼ ┴╬ ╧╞╞╙┼╘
  420. ; ┴╬─ ╙┼┴╥├╚ ╘╚┼ ─╔├╘╔╧╬┴╥┘ ╞╧╥ ╘╚┼ ╥╔╟╚╘ ═┴╘├╚ ╧╥ ┴ ┼═╨╘┘
  421. ; ╙╨┴├┼ ╔╙ ╞╧╒╬─. ╔╞ ┴╬ ┼═╨╘┘ ╙╨┴├┼ ╔╙ ╞╧╒╬─ ╘╚┼╬ ╘╚┴╘ ├╚┴╥┴├╘┼╥ ┴╬─
  422. ; ╙╘╥╔╬╟├╧─┼ ├╧═┬╔╬┴╘╔╧╬ ╔╙ ╬╧╘ ╔╬ ╘╚┼ ─╔├╘╔╧╬┴╥┘
  423.  
  424. ╞╔╬─╬╧─┼ ╠─┴ #0
  425. ╙╘┴ ╔╬─┼╪+1
  426. ╠─┴ ├╚┴╥┴├╘┼╥     ; ╚┼╥┼ ╘╚┼ ╚┴╙╚╔╬╟ ╞╒╬├╘╔╧╬ ╔╙ ┴╨╨╠╔┼─ ╘╧ ╘╚┼
  427. ┴╙╠               ; ├╚┴╥┴├╘┼╥ ┴╬─ ╘╚┼ ╙╘╥╔╬╟ ├╧─┼. ╞╧╥ ╘╚╧╙┼ ╫╚╧
  428. ╥╧╠ ╔╬─┼╪+1       ; ├┴╥┼ ╘╚┼ ╚┴╙╚╔╬╟ ╞╧╥═╒╠┴ ╔╙:
  429. ┼╧╥ ╙╘╥╔╬╟├╧─┼    ; (├╚┴╥┴├╘┼╥ << 1) ^ ╙╘╥╔╬╟├╧─┼
  430. ╙╘┴ ╔╬─┼╪         ; ╞╔╬─ ╬╧─┼ ╫╔╠╠ ╠╧╧╨ ╘╔╠╠ ╔╘ ╞╔╬─╙ ┴ ╬╧─┼
  431. ╠─┴ ╔╬─┼╪+1       ; ╘╚┴╘ ╚┴╙ ┴ ┼═╨╘┘ ╬╧─┼ ╧╥ ═┴╘├╚┼╙ ╘╚┼ ├╒╥╥┼╬╘
  432. ┼╧╥ ╙╘╥╔╬╟├╧─┼+1  ; ╨┴╥┼╬╘ ├╧─┼ ┴╬─ ├╚┴╥┴├╘┼╥
  433. ╙╘┴ ╔╬─┼╪+1
  434. ╧╥┴ ╔╬─┼╪ 
  435. ┬╬┼ +
  436.     ╠─╪ #1
  437.     ╙╘╪ ╧╞╞╙┼╘
  438.     ─┼╪
  439.     ╙╘╪ ╧╞╞╙┼╘+1
  440.     ╩═╨ ╞╧╥┼╓┼╠╧╧╨
  441. + ╙┼├
  442. ╠─┴ #<╘┴┬╠┼╙╔┌┼
  443. ╙┬├ ╔╬─┼╪
  444. ╙╘┴ ╧╞╞╙┼╘
  445. ╠─┴ #>╘┴┬╠┼╙╔┌┼
  446. ╙┬├ ╔╬─┼╪+1
  447. ╙╘┴ ╧╞╞╙┼╘+1
  448.  
  449. ╞╧╥┼╓┼╠╧╧╨ ╩╙╥ ├┴╠├╒╠┴╘┼     
  450.            ╠─┘ #0
  451.            ╠─┴ ($╞┼),┘
  452.            ╔╬┘
  453.            ┴╬─ ($╞┼),┘
  454.            ├═╨ #255
  455.            ┬╬┼ +
  456.                ╠─┘ #0
  457.                ╥╘╙
  458.            + ╔╬┘
  459.            - ╠─┴ ($╞┼),┘
  460.              ├═╨ ╙╘╥╔╬╟├╧─┼-2,┘
  461.              ┬╬┼ +
  462.              ╔╬┘
  463.              ├╨┘ #5
  464.              ┬╬┼ -
  465.           ╠─┘ #0
  466.           ╥╘╙
  467.           + ╙┼├
  468.           ╠─┴ ╔╬─┼╪
  469.           ╙┬├ ╧╞╞╙┼╘
  470.           ╙╘┴ ╔╬─┼╪
  471.           ╠─┴ ╔╬─┼╪+1
  472.           ╙┬├ ╧╞╞╙┼╘+1
  473.           ╙╘┴ ╔╬─┼╪+1
  474.           ┴╬─ #128
  475.           ┬┼╤ ╞╧╥┼╓┼╠╧╧╨
  476.           ├╠├
  477.           ╠─┴ #<╘┴┬╠┼╙╔┌┼
  478.           ┴─├ ╔╬─┼╪
  479.           ╙╘┴ ╔╬─┼╪
  480.           ╠─┴ #>╘┴┬╠┼╙╔┌┼
  481.           ┴─├ ╔╬─┼╪+1
  482.           ╙╘┴ ╔╬─┼╪+1
  483. ╩═╨ ╞╧╥┼╓┼╠╧╧╨
  484.  
  485. ;***************************
  486. ; ├┴╠├╒╠┴╘┼
  487. ; ╘┴╦┼╙ ╘╚┼ ╓┴╠╒┼ ╔╬ ╔╬─┼╪ ┴╬─ ├┴╠├╒╠┴╘┼╙ ╔╘╙ ╠╧├┴╘╔╧╬ ╔╬ ╘╚┼ ─╔├╘╔╧╬┴╥┘
  488. ;****************************
  489.  
  490. ├┴╠├╒╠┴╘┼ ╠─┴ ╔╬─┼╪
  491. ╙╘┴ $╞┼
  492. ╠─┴ ╔╬─┼╪+1
  493. ╙╘┴ $╞╞
  494. ┴╙╠ $╞┼
  495. ╥╧╠ $╞╞
  496. ┴╙╠ $╞┼
  497. ╥╧╠ $╞╞
  498. ├╠├
  499. ╠─┴ ╔╬─┼╪
  500. ┴─├ $╞┼
  501. ╙╘┴ $╞┼
  502. ╠─┴ ╔╬─┼╪+1
  503. ┴─├ $╞╞
  504. ╙╘┴ $╞╞
  505. ├╠├
  506. ╠─┴ #<╘┴┬╠┼┬┴╙┼
  507. ┴─├ $╞┼
  508. ╙╘┴ $╞┼
  509. ╠─┴ #>╘┴┬╠┼┬┴╙┼
  510. ┴─├ $╞╞
  511. ╙╘┴ $╞╞
  512. ╠─┘ #0
  513. ╥╘╙
  514.  
  515. ;******************************
  516. ; ─┼├╧─┼╙╘╥╔╬╟
  517. ;******************************
  518.  
  519. ─┼├╧─┼╙╘╥╔╬╟ ╘┘┴   ; ─┼├╧─┼╙╘╥╔╬╟ ╨╒╘╙ ╘╚┼ ╙╘╥╔╬╟ ╧╬ ╘╚┼ ╙╘┴├╦
  520. ╙╘┴ ├╧╒╬╘          ; ╔╬ ┴ ╠╔╞╧ ╞┴╙╚╔╧╬.
  521. ╠─╪ #>─┼├╧─┼╙╘┴├╦
  522. ├╠├
  523. ┴─├ #<─┼├╧─┼╙╘┴├╦
  524. ╙╘┴ $╞├
  525. ╙╘╪ $╞─
  526. ╠─┴ #0
  527. ╙╘┴ ├╧╒╬╘+1
  528. - ╠─┴ ╔╬─┼╪+1
  529.   ┬┼╤ +
  530.   ╩╙╥ ├┴╠├╒╠┴╘┼
  531.   ╠─┘ #4
  532.   ╠─┴ ($╞┼),┘
  533.   ╠─┘ #0
  534.   ╙╘┴ ($╞├),┘
  535.   ╠─┘ #2
  536.   ╠─┴ ($╞┼),┘
  537.   ╙╘┴ ╔╬─┼╪
  538.   ╔╬┘
  539.   ╠─┴ ($╞┼),┘
  540.   ╙╘┴ ╔╬─┼╪+1
  541.   ╩╙╥ ╔╬╞├
  542. ╩═╨ -
  543. + ╠─┘ #0
  544. ╠─┴ ╔╬─┼╪
  545. ╙╘┴ ($╞├),┘
  546. ╔╬├ ├╧╒╬╘
  547. ┬╬┼ +
  548.     ╔╬├ ├╧╒╬╘+1
  549. + ╥╘╙
  550.  
  551. ;******************************
  552. ; ╔╬╨╒╘
  553. ;******************************
  554.  
  555. ╔╬╨╒╘ ╠─┴ #0  ; ╘╚┼ ╔╬╨╒╘ ╥╧╒╘╔╬┼╙ ╔╙ ╒╙┼─ ┬┘ ╘╚┼ ─┼├╧═╨╥┼╙╙╧╥
  556. ╙╘┴ ═┴╙╦+1    ; ╘╧ ╥┼┴─ ╔╬ ╘╚┼ ╓┴╥╔┴┬╠┼ ╠┼╬╟╘╚ ├╧─┼╙
  557. ╙╘┴ ╥┼╘╒╥╬
  558. ╙╘┴ ╥┼╘╒╥╬+1
  559. ╠─┴ #1
  560. ╠─╪ ├╒╥╥┼╬╘┬╔╘╙
  561. ─┼╪
  562. - ┴╙╠
  563.   ╥╧╠ ═┴╙╦+1
  564.   ─┼╪
  565. ┬╬┼ -
  566. ╙╘┴ ═┴╙╦
  567. - ╠─┴ ═┴╙╦
  568.   ╧╥┴ ═┴╙╦+1
  569.   ┬┼╤ ╔╬╨╒╘─╧╬┼
  570.   ╠─┴ ┬╔╘═┴╙╦
  571.   ┬╨╠ +
  572.       ╩╙╥ ╟┼╘├╚┴╥
  573.       ╙╘┴ ╥┴├╦
  574.   + ╠─┴ ╥┴├╦
  575.   ┴╬─ ┬╔╘═┴╙╦
  576.   ┬┼╤ +
  577.       ╠─┴ ═┴╙╦
  578.       ╧╥┴ ╥┼╘╒╥╬
  579.       ╙╘┴ ╥┼╘╒╥╬
  580.       ╠─┴ ═┴╙╦+1
  581.       ╧╥┴ ╥┼╘╒╥╬+1
  582.       ╙╘┴ ╥┼╘╒╥╬+1
  583.   + ╠╙╥ ═┴╙╦+1
  584.   ╥╧╥ ═┴╙╦
  585.   ╠╙╥ ┬╔╘═┴╙╦
  586.   ╠─┴ ┬╔╘═┴╙╦
  587.   ┬╬┼ +
  588.       ╠─┴ #128
  589.       ╙╘┴ ┬╔╘═┴╙╦
  590. + ╩═╨ -
  591. ╔╬╨╒╘─╧╬┼ ╥╘╙
  592.  
  593. ;*******************************
  594. ; ┼╪╨┴╬─╞╔╠┼
  595. ; ╫╚┼╥┼ ╘╚┼ ─┼├╧═╨╥┼╙╙╔╧╬ ╔╙ ─╧╬┼
  596. ;*******************************
  597.  
  598. ┼╪╨┴╬─╞╔╠┼ ╠─┴ #0
  599. ╙╘┴ ╥┴├╦
  600. ╠─┴ #128
  601. ╙╘┴ ┬╔╘═┴╙╦
  602. ╙╘┴╥╘ ╩╙╥ ╔╬╔╘─╔├
  603. ╩╙╥ ╔╬╨╒╘
  604. ╠─┴ ╥┼╘╒╥╬+1
  605. ╙╘┴ ╧╠─├╧─┼+1       ; ╙AVE THE FIRST CHARACTER IN ╧╠─├╧─┼
  606. ╠─┴ ╥┼╘╒╥╬
  607. ╙╘┴ ├╚┴╥┴├╘┼╥
  608. ╙╘┴ ╧╠─├╧─┼
  609. ├═╨ #<┼╧╙
  610. ┬╬┼ +
  611.     ╠─┴ ╥┼╘╒╥╬+1    ; ╔F RETURN = ┼╧╙ (256) THEN ALL DONE 
  612.     ├═╨ #>┼╧╙
  613.     ┬╬┼ +
  614.     ╩═╨ ├╠╧╙┼
  615. + ╩╙╥ $╞╞├├
  616. ╠─╪ #3
  617. ╩╙╥ $╞╞├9
  618. ╠─┴ ╧╠─├╧─┼         ; ╙END OLDCODE TO THE OUTPUT FILE
  619. ╩╙╥ $╞╞─2
  620. ╬┼╪╘ ╩╙╥ ╔╬╨╒╘
  621.      ╠─┴ ╥┼╘╒╥╬
  622.      ╙╘┴ ╬┼╫├╧─┼
  623.      ╠─┴ ╥┼╘╒╥╬+1
  624.      ╙╘┴ ╬┼╫├╧─┼+1
  625.      ├═╨ #1         ; ┴LL OF THE SPECIAL CODES ╞LUSHCODE,┬UMP├ODE & ┼╧╙
  626.      ┬╬┼ ++         ; ╚AVE 1 FOR A ═╙┬.
  627.          ╠─┴ ╬┼╫├╧─┼
  628.          ├═╨ #<┬╒═╨├╧─┼
  629.          ┬╬┼ +
  630.              ╔╬├ ├╒╥╥┼╬╘┬╔╘╙
  631.              ╩═╨ ╬┼╪╘
  632.          + ├═╨ #<╞╠╒╙╚├╧─┼
  633.          ┬┼╤ ╙╘┴╥╘
  634.          ├═╨ #<┼╧╙
  635.          ┬╬┼ +
  636.          ╩═╨ ├╠╧╙┼
  637.      + ╙┼├          ; ╚ERE WE COMPARE THE NEWCODE JUST READ IN TO THE
  638.      ╠─┴ ╬┼╫├╧─┼    ; NEXT CODE. ╔F NEWCODE IS GREATER THAN IT IS A 
  639.      ╙┬├ ╬┼╪╘├╧─┼   ; ┴├╒╘┼┴├╒╘┼┴ SITUATION AND MUST BE HANDLE DIFFERENTLY.
  640.      ╙╘┴ 3
  641.      ╠─┴ ╬┼╫├╧─┼+1 
  642.      ╙┬├ ╬┼╪╘├╧─┼+1
  643.      ╧╥┴ 3
  644.      ┬├├ +
  645.          ╠─┴ ├╚┴╥┴├╘┼╥
  646.          ╙╘┴ ─┼├╧─┼╙╘┴├╦
  647.          ╠─┴ ╧╠─├╧─┼
  648.          ╙╘┴ ╔╬─┼╪
  649.          ╠─┴ ╧╠─├╧─┼+1
  650.          ╙╘┴ ╔╬─┼╪+1
  651.          ╠─┘ #1
  652.          ┬╬┼ ++
  653.      + ╠─┴ ╬┼╫├╧─┼  ; ╨OINT INDEX TO NEWCODE SPOT IN THE DICTIONARY   
  654.      ╙╘┴ ╔╬─┼╪      ; ╙O ─┼├╧─┼╙╘╥╔╬╟ HAS A PLACE TO START
  655.      ╠─┴ ╬┼╫├╧─┼+1
  656.      ╙╘┴ ╔╬─┼╪+1
  657.      ╠─┘ #0
  658.      + ╩╙╥ ─┼├╧─┼╙╘╥╔╬╟
  659.      ╠─┘ #0
  660.      ╠─┴ ($╞├),┘
  661.      ╙╘┴ ├╚┴╥┴├╘┼╥
  662.      ╔╬├ $╞├
  663.      ┬╬┼ +
  664.          ╔╬├ $╞─
  665.      + ╩╙╥ $╞╞├├
  666.      ╠─╪ #3
  667.      ╩╙╥ $╞╞├9
  668.      ╠1 ╠─┴ ├╧╒╬╘+1  ; ├OUNT CONTAINS THE NUMBER OF CHARACTERS ON THE STACK
  669.         ╧╥┴ ├╧╒╬╘
  670.         ┬┼╤ +       
  671.         ╩╙╥ ─┼├╞├
  672.         ╠─┘ #0
  673.         ╠─┴ ($╞├),┘
  674.         ╩╙╥ $╞╞─2
  675.      ╩═╨ ╠1
  676.      + ╠─┴ ╬┼╪╘├╧─┼  ; ├ALCULATE THE SPOT IN THE DICTIONARY FOR THE STRING
  677.      ╙╘┴ ╔╬─┼╪       ; THAT WAS JUST ENTERED.
  678.      ╠─┴ ╬┼╪╘├╧─┼+1
  679.      ╙╘┴ ╔╬─┼╪+1
  680.      ╩╙╥ ├┴╠├╒╠┴╘┼
  681.      ╠─┘ #2          ; ╘HE LAST CHARACTER READ IN IS TACKED ONTO THE END
  682.      ╠─┴ ╧╠─├╧─┼     ; OF THE STRING THAT WAS JUST TAKEN OFF THE STACK
  683.      ╙╘┴ ($╞┼),┘     ; ╘HE NEXTCODE IS THEN INCREMENTED TO PREPARE FOR THE 
  684.      ╔╬┘             ; NEXT ENTRY.
  685.      ╠─┴ ╧╠─├╧─┼+1
  686.      ╙╘┴ ($╞┼),┘
  687.      ╔╬┘
  688.      ╠─┴ ├╚┴╥┴├╘┼╥
  689.      ╙╘┴ ($╞┼),┘
  690.      ╔╬├ ╬┼╪╘├╧─┼
  691.      ┬╬┼ +
  692.          ╔╬├ ╬┼╪╘├╧─┼+1
  693.      + ╠─┴ ╬┼╫├╧─┼
  694.      ╙╘┴ ╧╠─├╧─┼
  695.      ╠─┴ ╬┼╫├╧─┼+1
  696.      ╙╘┴ ╧╠─├╧─┼+1
  697. ╩═╨ ╬┼╪╘
  698. ├╠╧╙┼ ╩╙╥ $╞╞├├
  699. ╠─┴ #2
  700. ╩╙╥ $╞╞├3
  701. ╠─┴ #3
  702. ╩═╨ $╞╞├3
  703.  
  704. ─┼├╞├ ╠─┴ $╞├
  705. ┬╬┼ +
  706.     ─┼├ $╞─
  707. + ─┼├ $╞├
  708. ╠─┴ ├╧╒╬╘
  709. ┬╬┼ +
  710.     ─┼├ ├╧╒╬╘+1
  711. + ─┼├ ├╧╒╬╘
  712. ╥╘╙
  713. ╔╬╞├ ╔╬├ $╞├
  714. ┬╬┼ +
  715.     ╔╬├ $╞─
  716. + ╔╬├ ├╧╒╬╘
  717. ┬╬┼ +
  718.     ╔╬├ ├╧╒╬╘+1
  719. + ╥╘╙
  720.  
  721. ╬┼╪╘├╧─┼ .╫╧╥ 0
  722. ╙╘╥╔╬╟├╧─┼ .╫╧╥ 0
  723. ├╚┴╥┴├╘┼╥ .┬┘╘ 0
  724. ╬┼╪╘┬╒═╨ .╫╧╥ 0
  725. ├╒╥╥┼╬╘┬╔╘╙ .┬┘╘ 0
  726. ╥┴├╦ .┬┘╘ 0
  727. ┬╔╘═┴╙╦ .┬┘╘ 0
  728. ═┴╙╦ .╫╧╥ 0
  729. ╔╬─┼╪ .╫╧╥ 0
  730. ╧╞╞╙┼╘ .╫╧╥ 0
  731. ╥┼╘╒╥╬ .╫╧╥ 0
  732. ├╧╒╬╘ .╫╧╥ 0
  733. ╬┼╫├╧─┼ .╫╧╥ 0
  734. ╧╠─├╧─┼ .╫╧╥ 0
  735. ╘┼╙╘ .┬┘╘ 0
  736.  
  737. ╘╧ ─╥╔╓┼ ╘╚┼ ═╠ ╔ ╫╥╧╘┼ ╘╚╔╙ ╙═┴╠╠ ┬┴╙╔├ ╨╥╧╟╥┴═. ╬╧╘┼ ╘╚┴╘ ├╚┴╬╬┼╠ ╘╫╧ ╔╙
  738. ┴╠╫┴┘╙ ╘╚┼ ╔╬╨╒╘ ┴╬─ ├╚┴╬╬┼╠ ╘╚╥┼┼ ╔╙ ┴╠╫┴┘╙ ╘╚┼ ╧╒╘╨╒╘. ┼╪ ┴╬─ ├╧ ═┴┘ ┬┼
  739. ├╚┴╬╟┼─ ╘╧ ╙╒╔╘ ╫╚┴╘┼╓┼╥ ╠╧├┴╘╔╧╬╙ ╘╚┼ ╨╥╧╟╥┴═ ╔╙ ╥┼┴╙╙┼═┬╠┼─ ┴╘.
  740.  
  741. 1 ╔╞┴=.╘╚┼╬┴=1:╠╧┴─"╠┌╫.═╠",╨┼┼╦(186),1
  742. 10 ┼╪=2500:├╧=2503
  743. 15 ╨╥╔╬╘"[┼]╪╨┴╬─ ╧╥ [├]╧═╨╥┼╙╙?"
  744. 20 ╟┼╘┴$:╔╞┴$<>"├"┴╬─┴$<>"┼"╘╚┼╬20
  745. 30 ╔╬╨╒╘"╬┴═┼ ╧╞ ╔╬╨╒╘ ╞╔╠┼";╞╔$:╔╞╠┼╬(╞╔$)=.╘╚┼╬30
  746. 40 ╔╬╨╒╘"╬┴═┼ ╧╞ ╧╒╘╨╒╘ ╞╔╠┼";╞╧$:╔╞╠┼╬(╞╧$)=.╘╚┼╬40
  747. 50 ╧╨┼╬2,9,2,╞╔$+",╨,╥":╧╨┼╬3,9,3,╞╧$+",╨,╫"
  748. 60 ╔╞┴$="┼"╘╚┼╬╙┘╙┼╪
  749. 70 ╔╞┴$="├"╘╚┼╬╙┘╙├╧
  750. 80 ┼╬─
  751.  
  752. ╞OR THOSE INTERESTED IN LEARNING MORE ABOUT DATA
  753. COMPRESSION/DECOMPRESSION ╔ RECOMMEND THE BOOK '╘HE ─ATA ├OMPRESSION
  754. ┬OOK' WRITTEN BY ═ARK ╬ELSON. ╔ LEARNED A GREAT DEAL FROM READING THIS
  755. BOOK. ╔T EXPLAINS ALL OF THE MAJOR DATA COMPRESSION METHODS. (HUFFMAN
  756. CODING, DICTIONARY TYPE COMPRESSION SUCH AS ╠┌╫, ARITHMATIC CODING,
  757. SPEECH COMPRESSION AND LOSSY GRAPHICS COMPRESSION)
  758.  
  759. ╤UESTIONS OR COMMENTS ARE WELCOME, THEY MAY BE DIRECTED TO ME AT :
  760.  
  761. ╔NTERNET   : ┬LUCIER@ERSYS.EDMONTON.AB.CA
  762. ╟ENIE      : B.LUCIER1
  763.  
  764. ------------------------------------------------------------------------------
  765.  
  766. BEGIN 644 LZW.ML
  767. ═╤└┼,╬└╨@╟╨╩╔@(╫╘#:─└├?,-(.╠*├>╘-╩0"-[@╘@┌╨╩-[╨╘@6└╬╤_╠@╤_╠╟_
  768. ═\└┌╤_╚╫╬#8┬╤_╚╫═#4╤╚"╩└└╬>╠-─?[(╨└70]╬[╦#=└#[╬╨-(/8*╦>╨-╥1#0
  769. ═&╩╫╦#<─└╘!.╔└╚╫═#:─!├>╪-(/8*()\*3%╘*╦?$-╙>╨-╘!┌═\└╫-┌╨╫0%╩─!
  770. ═├>╪-╩0&-[0╘@]@╦╬\@╘.\└╘╬\0╓╔└(╫╬#:╫╧#8╫═#:60╘└-,╫╨─@]@╩╔└8╫╬
  771. ═#:─└├>╘-(/8*╦?0-\└╪@╙/^┬└╥#)_┌╫╙#2#2_╥#,_┌─#(,/_╩0),╨_^╔"8╫╥
  772. ═#:─!├>╨-╩0.-┌╨╓╔└╚╫╤#:─└├?└-╩0"%_╩─╪┴?^╔╟87\╩1.%_:└└╩?^1_╠┬1
  773. ═_┴┬╔!67^┴?┌0└╬;_╔?╙0└╠;]╤╧╥┼_07\╘-┘@(,╙_╚@(@╤╧],╙_^╔└(╫╓#:─!
  774. ═╦╧(-╥@╚╬]@╫*╘/╞-]0╓═]0╘-]@╫0└6"═]0╘═[0╓%└┌╫╓#2╫╬#04#\└╞═\╨╘-
  775. ═]└╓-\╨╒.]└╓═]└╫0&"#,_┌(#(,╟_╦?,-(-+_╩0"-\╨╓╔@(╫╘#4[╓#6[╒#4╨+
  776. ═"┌─└├?@-╦>\-"┬[╪#4╫═#8╫╫#:╫╪#4╫╬#8╫╪#=└1╦?<-╘└╥┬└8[┘#<╩.^@╒,
  777. ═┼╨╠╪╩9╫═]╨╓-^0╓╔$^╫╪#8╫┌#2#├"┌└└╠?[(,?[)_]└#╚└!@╥+'^╓>╠-╘└├(
  778. ═╨└70]*└└8#┬═]╨╫═^0╓-]╨╓═^└╫═^@╓-^└╘╔@/└1&*╞=;?<-├?<-╩1-═^└╓-
  779. ═^└╒,┼╨╬═]╨╓%_╩╫╪#87_!╧╪╞_╨;^)╧\8╦?<-9?┌%_╩╫╪#67_┴?\8╩0!┼_╚7^
  780. ═╩3┴┼_╪7_╚└!@╞(╫]#:(─&&┼4┴?╥&_:─└├?╪-╦?@-\!╪@╪╨╬@!+'^╚└"1_*└"
  781. ═╠?┌-]╨╫(╠?┌-^└╘@╫└╒,)@╥@└*╫╫#9'\[╧╘-╘└/╬_@╒@╩0"-]@╓-^╨╓-_└╓╔
  782. ═└:[╥#<╚*+╧8-╥═#┘├?4-╦?4-#?8-\#╬═]└╘0!┬#╦"╚╫╙#:╫╙#2╫╘#?└2╦?4-
  783. ═#?╠-├?╠-╦?8-#?╨-├?╨-3╧8-;╧4-3╧0-╦?0-╘└6╔@(╫╘#4╤╘#&"╔└(╫╙#:╞└
  784. ═├?0-()\*(%─,╦?╨-├0(.╦?╠-├>\-├0$.╥0#0"╩╫\#<─!╘└-,╬╨╘@╙/^┬└╥#)
  785. ═_┌╘!#┬#2_╥!9#*╫[#8╫_#:╫\#8╘└#╠─!╘!┬═_╨╫)└=└&[╧(-3/,,╥0+╨╩\─└
  786. ═╘└-,╬╨╘╪╦?\-[>╠-┴0.═└└[═[└╘%└┘└6╦>\-├50─╦0$.├?<-╦0(.├?@-╚└'0
  787. ═#╩╫_#8╫╫#:╘└#╚╫╪#:└└(!0,╚└"╤_(╫╧#>;\╘└+╞_2#,_┌(#(,╟_╦?╪-#?╘-
  788. ═\└╘@╥└╓@└+'\(-+_3&╘-╦>╠-├?<-╦>╨-├?@-(.,+╚└*═└0┌1_╠┬═└@┌1_╠┬═
  789. ═[╨╓1_╬[╦#=└#[╬╨-╦?\-├0$.╦0└.├0(.3/,,(,╙_╩0(@╨_^╔└╘╙#_┌7\╘└+&
  790. ═_<;\╦?╘-╘└/._@╫._0╒@┘╧╙0└╬;][╧╘-╘└/╬_@╒@└└└└└└└└└└└└└└└└└└└└
  791. *└└└└└└└└└└└└└└└└
  792. END
  793.  
  794. CRC32 FOR LZW.ML = 2460116527
  795.  
  796. BEGIN 644 LZW.BAS
  797. ═└0@<"└$└┬╘&╥+╩=!╠├$┌─╥),6┼<╬34╨┬+#─╠,0└╨"└╚└15┬╥,├4╨,#╔#3[(╥
  798. ═-3└╙└%└(#╨"9(╔,219)84$%.1"!/4┬└20┘)/35!215-3/╥(└;└@4└*%!)#╩+
  799. ═022╙╠2)#(╩]!)+.╤(─4┬╔╙(╨└)<('@"%(─┘!344@3╘8@24┘0550@1─┼,12([
  800. ═1───.╚╧#*$9))"╞╥+╩<╙,└##""@└┴2).04╒%($]&($]55%!55"!&24╤%(├═&
  801. ═3╥0┌┬\,╚1─\─*;(╬╔╙0╨└.╠(,@"?,┬╨┘+#(╠1───╩┬(╠4╥╤2(├╩?,╥╨┘+#,╠
  802. ═1─\─╩┬(╠4"╤7(@#["#╨└┬╘$─╠┬)%(╩>>15@└"╨┼&└(═!)+(┬0╥*╟╟─-/└└└└
  803. END
  804.  
  805. CRC32 FOR LZW.BAS = 100674089
  806.  
  807. ===============================================================================
  808. ╘╚╥┼┼-╦┼┘ ╥╧╠╠╧╓┼╥ FOR THE ├-128 AND ├-64.
  809. BY ├RAIG ┬RUCE  <CSBRUCE@NEUMANN.UWATERLOO.CA>
  810.  
  811. 1. ╔╬╘╥╧─╒├╘╔╧╬
  812.  
  813. ╘HIS ARTICLE EXAMINES A THREE-KEY ROLLOVER MECHANISM FOR THE KEYBOARDS OF THE
  814. ├-128 AND ├-64 AND PRESENTS ╦ERNAL-WEDGE IMPLEMENTATIONS FOR BOTH MACHINES.
  815. ╫EBSTER'S DOESN'T SEEM TO KNOW, SO ╔'LL TELL YOU THAT THIS MEANS THAT THE
  816. MACHINE WILL ACT SENSIBLY IF YOU ARE HOLDING DOWN ONE KEY AND THEN PRESS
  817. ANOTHER WITHOUT RELEASING THE FIRST (OR EVEN PRESS A THIRD KEY WHILE HOLDING
  818. DOWN TWO OTHERS).  ╘HIS IS USEFUL TO FAST TOUCH TYPERS.  ╔N FACT, FAST TYPING
  819. WITHOUT ROLLOVER CAN BE QUITE ANNOYING; YOU GET A LOT OF MISSING LETTERS.
  820.  
  821. ┴NOTHER ANNOYING PROPERTY OF THE KERNEL KEYSCANNING IS JOYSTICK INTERFERENCE.
  822. ╔F YOU MOVE THE JOYSTICK PLUGGED INTO PORT #1, YOU WILL NOTICE THAT SOME JUNK
  823. KEYSTROKES RESULT.  ╘HE KEYSCANNERS HERE ELIMINATE THIS PROBLEM BY SIMPLY
  824. CHECKING IF THE JOYSTICK IS PRESSED AND IGNORING THE KEYBOARD IF IT IS.
  825.  
  826. ╘HE REASON THAT A 3-KEY ROLLOVER IS IMPLEMENTED INSTEAD OF THE MORE GENERAL
  827. ╬-KEY ROLLOVER IS THAT SCANNING THE KEYBOARD BECOMES MORE AND MORE UNRELIABLE
  828. AS MORE KEYS ARE HELD DOWN.  ╦EY "SHADDOWS" BEGIN TO APPEAR TO MAKE IT LOOK
  829. LIKE YOU ARE HOLDING DOWN A CERTAIN KEY WHEN YOU REALLY ARE NOT.  ╙O, BY
  830. LIMITING THE NUMBER OF KEYS SCANNED TO 3, SOME OF THIS CAN BE AVOIDED.  ┘OU
  831. WILL GET STRANGE RESULTS IF YOU HOLD DOWN MORE THAN THREE KEYS AT A TIME, AND
  832. EVEN SOMETIMES WHEN HOLDING DOWN 3 OR LESS.  ╘HE "SHIFT" KEYS (╙HIFT,
  833. ├OMMODORE, ├ONTROL, ┴LTERNATE, AND ├APS╠OCK) DON'T COUNT IN THE 3 KEYS OF
  834. ROLLOVER, BUT THEY DO MAKE THE KEYBOARD HARDER TO READ CORRECTLY.
  835. ╞ORTUNATELY, THREE KEYS WILL ALLOW YOU TO TYPE WORDS LIKE "┴╬─" AND "╘╚┼"
  836. WITHOUT RELEASING ANY KEYS.
  837.  
  838. 2. ╒╙┼╥ ╟╒╔─┼
  839.  
  840. ╒SING THESE UTILITIES IS REALLY EASY - YOU JUST TYPE AWAY LIKE NORMAL.  ╘O
  841. INSTALL THE ├-128 VERSION, ENTER:
  842.  
  843. ┬╧╧╘ "╦┼┘╙├┴╬128"
  844.  
  845. AND YOU'RE IN BUSINESS.  ╘HE PROGRAM WILL DISPLAY "╦EYSCAN128 INSTALLED" AND
  846. GO TO WORK.  ╘HE PROGRAM LOADS INTO MEMORY AT ADDRESSES $1500-$17┬┴ (5376-6074
  847. DECIMAL), SO YOU'LL WANT TO WATCH OUT FOR CONFLICTS WITH OTHER UTILITIES.
  848. ╘HIS PROGRAM ALSO TAKES OVER THE ╔╥╤ VECTOR AND THE ┬┴╙╔├ RESTART VECTOR
  849. ($┴00).  ╘HE PROGRAM WILL SURVIVE A ╥╒╬/╙╘╧╨+╥┼╙╘╧╥┼.  ╘O UNINSTALL THIS
  850. PROGRAM, YOU MUST RESET THE MACHINE (OR POKE THE KERNEL VALUES BACK INTO THE
  851. VECTORS); IT DOES NOT UNINSTALL ITSELF.
  852.  
  853. ╠OADING THE ├-64 VERSION IS A BIT TRICKIER, SO A SMALL ┬┴╙╔├ LOADER PROGRAM IS
  854. PROVIDED.  ╠╧┴─ AND ╥╒╬ THE "╦┼┘╙├┴╬64.┬╧╧╘" PROGRAM.  ╔T WILL LOAD THE
  855. "╦┼┘╙├┴╬64" PROGRAM INTO MEMORY AT ADDRESSES $├500-$├77┼ (50432-51070 DECIMAL)
  856. AND EXECUTE IT (WITH A ╙┘╙ 50432).  ╘O UNINSTALL THE PROGRAM, ENTER ╙┘╙ 50435.
  857. ╘HE PROGRAM TAKES OVER THE ╔╥╤ AND ╬═╔ VECTORS AND ONLY GIVES THEM BACK TO THE
  858. KERNEL UPON UNINSTALLATION.  ╘HE PROGRAM WILL SURVIVE A ╥╒╬/╙╘╧╨+╥┼╙╘╧╥┼.
  859.  
  860. ╙OMETHING THAT YOU MAY OR MAY NOT KNOW ABOUT THE ├-64 IS THAT ITS KEYS CAN BE
  861. MADE TO REPEAT BY POKING TO ADDRESS 650 DECIMAL.  ╨╧╦┼650,128 WILL ENABLE THE
  862. REPEATING OF ALL KEYS.  ╨╧╦┼650,0 WILL ENABLE ONLY THE REPEATING OF THE ╙╨┴├┼,
  863. ─┼╠┼╘┼, AND ├╒╥╙╧╥ KEYS.  ╨╧╦┼650,64 WILL DISABLE THE REPEATING OF ALL KEYS.
  864. ┴N UNUSUAL SIDE EFFECT OF CHANGING THIS TO EITHER FULL REPEAT OR NO REPEAT IS
  865. THAT HOLDING DOWN ╙╚╔╞╘+├╧══╧─╧╥┼ (CHARACTER SET SHIFT) WILL REPEAT RAPIDLY.
  866.  
  867. ╘O SEE THE ROLLOVER IN ACTION, HOLD DOWN THE "╩" KEY FOR A WHILE, AND THEN
  868. PRESS "╦" WITHOUT RELEASING "╩".  "╦" WILL COME OUT AS EXPECTED, AS IT WOULD
  869. WITH THE KERNAL.  ╬OW, RELEASE THE "╩" KEY.  ╔F YOU ARE ON A ├-128, YOU WILL
  870. NOTICE THAT THE "╦" KEY WILL NOW STOP REPEATING (THIS IS ACTUALLY AN IMPORTANT
  871. FEATURE - IT AVOIDS PROBLEMS IF YOU DON'T RELEASE ALL OF THE KEYS YOU ARE
  872. HOLDING DOWN, AT ONCE).  ╬OW, PRESS AND HOLD THE "╩" KEY AGAIN WITHOUT
  873. RELEASING THE "╦".  "╩" WILL NOW APPEAR.  ╔T WOULDN'T USING THE ╦ERNAL KEY
  874. SCANNER.  ┘OU CAN ALSO TRY THIS WITH 3-KEY COMBINATIONS.  ╘HERE WILL BE SOME
  875. COMBINATIONS THAT CAUSE PROBLEMS; MORE ON THIS BELOW.
  876.  
  877. ┴LSO, TAKE A SPAZ ON THE JOYSTICK PLUGGED INTO PORT #1 AND OBSERVE THAT NO
  878. GARBAGE GETS TYPED IN.  ╘HIS WAS AN ANNOYING PROBLEM WITH THE KERNEL OF BOTH
  879. THE 64 AND 128 AND HAS LEAD MANY DIFFERENT GAMES TO PICKING BETWEEN JOYSTICK
  880. #1 AND #2 AS THE PRIMARY CONTROLLER.  ╘HE JOYSTICK IN PORT #2 IS NOT A PROBLEM
  881. TO EITHER ╦EYSCAN-128/64 OR THE ╦ERNAL.
  882.  
  883. 3. ╦┼┘┬╧┴╥─ ╙├┴╬╬╔╬╟
  884.  
  885. ╘HE ╦ERNAL SCANS THE KEYBOARD SIXTY TIMES A SECOND TO SEE WHAT KEYS YOU ARE
  886. HOLDING DOWN.  ┬ECAUSE OF HARDWARE PECULIARITIES, THERE ARE MULTIPLE SCANNING
  887. TECHNIQUES THAT WILL GIVE DIFFERENT RESULTS.
  888.  
  889. 3.1. ╙├┴╬╬╔╬╟ ┼╪┴═╨╠┼
  890.  
  891. ┴N EXAMPLE PROGRAM IS INCLUDED TO DEMONSTRATE DIFFERENT KEYBOARD SCANNING
  892. TECHNIQUES POSSIBLE.  ╘O RUN IT FROM A ├-128 IN 40-COLUMN (SLOW) MODE, ENTER:
  893.  
  894. ┬╧╧╘ "╦┼┘╙╚╧╫"
  895.  
  896. ╧N A ├-64, YOU MUST:
  897.  
  898. ╠╧┴─ "╦┼┘╙╚╧╫",8,1
  899.  
  900. AND THEN:
  901.  
  902. ╙┘╙ 4864
  903.  
  904. ╘HE SAME PROGRAM WORKS ON BOTH MACHINES.  ╞OUR MAPS OF THE KEYSCANNING MATRIX
  905. WILL BE DISPLAYED ON THE 40-COLUMN SCREEN, AS SCANNED BY DIFFERENT TECHNIQUES.
  906. ╘HE LEFTMOST ONE IS SCANNED FROM TOP TO BOTTOM "QUICKLY".  ╘HE SECOND FROM THE
  907. LEFT SCANS FROM BOTTOM TO TOP "QUICKLY".  ╘HE THIRD FROM THE LEFT SCANS THE
  908. KEYBOARD SIDEWAYS, AND THE RIGHTMOST MATRIX SCANS THE KEYS FROM TOP TO BOTTOM
  909. "SLOWLY".
  910.  
  911. ╘HE MAPPING OF KEYSCAN MATRIX POSITIONS TO KEYS IS AS FOLLOWS:
  912.  
  913. ╥╧╫╙: \             ├╧╠╒═╬╙:    PEEK($─├01)
  914. POKE   \
  915. $─├00   \   128      64      32      16      8       4       2       1
  916.          +-------+-------+-------+-------+-------+-------+-------+-------+
  917.   255-1  ▄ ─╧╫╬  ▄   ╞5  ▄   ╞3  ▄   ╞1  ▄   ╞7  ▄ ╥╔╟╚╘ ▄ ╥┼╘╒╥╬▄ ─┼╠┼╘┼▄
  918.          +-------+-------+-------+-------+-------+-------+-------+-------+
  919.   255-2  ▄╠┼╞╘-╙╚▄   ┼   ▄   ╙   ▄   ┌   ▄   4   ▄   ┴   ▄   ╫   ▄   3   ▄
  920.          +-------+-------+-------+-------+-------+-------+-------+-------+
  921.   255-4  ▄   ╪   ▄   ╘   ▄   ╞   ▄   ├   ▄   6   ▄   ─   ▄   ╥   ▄   5   ▄
  922.          +-------+-------+-------+-------+-------+-------+-------+-------+
  923.   255-8  ▄   ╓   ▄   ╒   ▄   ╚   ▄   ┬   ▄   8   ▄   ╟   ▄   ┘   ▄   7   ▄
  924.          +-------+-------+-------+-------+-------+-------+-------+-------+
  925.  255-16  ▄   ╬   ▄   ╧   ▄   ╦   ▄   ═   ▄   0   ▄   ╩   ▄   ╔   ▄   9   ▄
  926.          +-------+-------+-------+-------+-------+-------+-------+-------+
  927.  255-32  ▄   ,   ▄   @   ▄   :   ▄   .   ▄   -   ▄   ╠   ▄   ╨   ▄   +   ▄
  928.          +-------+-------+-------+-------+-------+-------+-------+-------+
  929.  255-64  ▄   /   ▄   ^   ▄   =   ▄╥╟╚╘-╙╚▄  ╚╧═┼ ▄   ;   ▄   *   ▄   \   ▄
  930.          +-------+-------+-------+-------+-------+-------+-------+-------+
  931. 255-128  ▄ ╙╘╧╨  ▄   ╤   ▄├╧══╧─╥▄ ╙╨┴├┼ ▄   2   ▄├╧╬╘╥╧╠▄   _   ▄   1   ▄
  932.          +-------+-------+-------+-------+-------+-------+-------+-------+
  933.  
  934. ╘HE FOLLOWING TABLE CONTAINS THE ADDITIONAL KEYS WHICH MUST BE SCANNED ON THE
  935. ├128 (BUT WHICH ARE NOT DISPLAYED BY THE EXAMPLE SCANNING PROGRAM).
  936.  
  937. ╥╧╫╙: \               ├╧╠╒═╬╙:    PEEK($─├01)
  938. POKE   \
  939. $─02╞   \   128      64      32      16      8       4       2       1
  940.          +-------+-------+-------+-------+-------+-------+-------+-------+
  941.   255-1  ▄   1   ▄   7   ▄   4   ▄   2   ▄  ╘┴┬  ▄   5   ▄   8   ▄  ╚┼╠╨ ▄
  942.          +-------+-------+-------+-------+-------+-------+-------+-------+
  943.   255-2  ▄   3   ▄   9   ▄   6   ▄ ┼╬╘┼╥ ▄   ╠╞  ▄   -   ▄   +   ▄  ┼╙├  ▄
  944.          +-------+-------+-------+-------+-------+-------+-------+-------+
  945.   255-4  ▄╬╧-╙├╥╠▄ ╥╔╟╚╘ ▄  ╠┼╞╘ ▄  ─╧╫╬ ▄   ╒╨  ▄   .   ▄   0   ▄  ┴╠╘  ▄
  946.          +-------+-------+-------+-------+-------+-------+-------+-------+
  947.  
  948. ╘HESE TABLES ARE PRESENTED ON PAGE 642 OF THE ├OMMODORE 128 ╨ROGRAMMER'S
  949. ╥EFERENCE ╟UIDE.  ╘HE SCAN CODES THAT ARE STORED IN LOCATION 212 ON THE ├128
  950. AND LOCATION 197 ON THE ├64 ARE CALCULATED BASED ON THE ABOVE TABLES.  ╘HE
  951. ENTRY IN THE "1" BIT POSITION OF THE FIRST LINE OF THE FIRST TABLE (─┼╠┼╘┼)
  952. HAS A SCAN CODE OF 0, THE "2" ENTRY (╥┼╘╒╥╬) HAS A SCAN CODE OF 1, ETC., THE
  953. ENTRY ON THE SECOND SCAN LINE IN THE "1" POSITION ("3") HAS A SCAN CODE OF 8,
  954. ETC., ALL THE WAY DOWN TO CODE 63.  ╘HE SCAN CODES FOR THE 128 GO ALL THE WAY
  955. TO 87, CONTINUING IN THE SECOND TABLE LIKE THE FIRST.
  956.  
  957. ┘OU WILL NOTICE SOME STRANGE EFFECTS OF THE DIFFERENT SCANNING TECHNIQUES WHEN
  958. YOU HOLD DOWN MULTIPLE KEYS.  ═ORE ON THIS BELOW.  ┴LSO TRY PUSHING JOYSTICK
  959. #1 AROUND.
  960.  
  961. 3.2. ╙├┴╬╬╔╬╟ ╚┴╥─╫┴╥┼
  962.  
  963. ╘O SCAN THE 128 KEYBOARD, YOU MUST POKE A VALUE INTO $─├00 (├╔┴#1 PORT ┴) AND
  964. $─02╞ (╓╔├ CHIP KEYBOARD SELECT PORT) TO SELECT THE ROW TO BE SCANNED.  ╘HE
  965. ─ATA ─IRECTION ╥EGISTER FOR THIS PORT WILL BE SET TO ALL OUTPUTS BY THE
  966. ╦ERNAL, SO YOU DON'T HAVE TO WORRY ABOUT IT.  ┼ACH BIT OF $─├00 AND THE THREE
  967. LEAST SIGNIFICANT BITS OF $─02╞ ARE USED FOR SELECTING ROWS.  ┴ "0" BIT MEANS
  968. THAT A ROW ╔╙ SELECTED, AND A "1" MEANS THAT A ROW ╔╙ ╬╧╘ SELECTED.  ╘HE POKE
  969. VALUE TO USE FOR SELECTING AMONG THE VARIOUS ROWS ARE GIVEN IN THE TWO TABLES
  970. IN THE PREVIOUS SECTION.
  971.  
  972. ╒SING ONE BIT PER ROW ALLOWS YOU TO SELECT MULTIPLE ROWS AT THE SAME TIME.  ╔T
  973. CAN BE USEFUL TO SELECT ALL ROWS AT ONE TIME OR NO ROWS.  ╘O READ THE ROW THAT
  974. HAS BEEN SELECTED, SIMPLY PEEK AT LOCATION $─├01 (├╔┴#1 PORT ┬).  ┼ACH BIT
  975. WILL TELL YOU WHETHER THE CORRESPONDING KEY IS CURRENTLY BEING HELD DOWN OR
  976. NOT.  ┴GAIN, WE HAVE REVERSE LOGIC; A "0" MEANS THAT THE KEY IS BEING HELD
  977. DOWN, AND A "1" MEANS THAT THE KEY IS NOT HELD DOWN.  ╘HE BIT VALUES
  978. CORRESPONDING TO THE KEYS ARE GIVEN AS THE COLUMN HEADINGS IN THE TABLES IN
  979. THE PREVIOUS SECTION.  ╙INCE THERE IS NO SUCH THING AS A PERFECT MECHANICAL
  980. SWITCH, IT IS RECOMMENDED THAT YOU "DEBOUNCE" EACH KEY ROW READ IN THE
  981. FOLLOWING WAY:
  982.  
  983. AGAIN:
  984.    LDA $DC01
  985.    CMP $DC01
  986.    BNE AGAIN
  987.  
  988. ╙O, TO SCAN THE ENTIRE KEYBOARD, YOU SIMPLY SELECT EACH SCAN ROW IN SOME
  989. ORDER, AND READ AND REMEMBER THE KEYS HELD DOWN ON THE ROW.  ┴S IT TURNS OUT,
  990. YOU HAVE TO BE A BIT CAREFUL OF EXACTLY HOW YOU "SELECT" A ROW.  ┴LSO, THERE
  991. IS A SHORTCUT THAT YOU CAN TAKE.  ╔N ORDER TO FIND OUT IF ANY KEY IS BEING
  992. HELD DOWN IN ONE OPERATION, ALL YOU HAVE TO DO IS SELECT ALL ROWS AT ONCE AND
  993. SEE IF THERE ARE ANY "0" BITS IN THE READ VALUE.  ╔F SO, THERE IS A KEY BEING
  994. HELD DOWN SOMEWHERE; IF NOT, THEN THERE IS NO KEY BEING HELD DOWN, SO YOU
  995. DON'T HAVE TO BOTHER SCANNING THE ENTIRE KEYBOARD.  ╘HIS WILL REDUCE OUR
  996. KEYSCANNING SIGNIFICANTLY, WHICH IS IMPORTANT, SINCE THE KEYBOARD WILL BE
  997. SCANNED EVERY 1/60 OF A SECOND.
  998.  
  999. ┴S MENTIONED ABOVE, JOYSTICK #1 WILL INTERFERE WITH THE ╦ERNAL READING THE
  1000. KEYBOARD.  ╘HIS IS BECAUSE THE READ VALUE OF JOYSTICK #1 IS WIRED INTO ├╔┴#1
  1001. PORT ┴, THE SAME PLACE THAT THE KEYBOARD READ IS WIRED IN.  ╙O, WHENEVER A
  1002. SWITCH IN THE JOYSTICK IS PUSHED, THE CORRESPONDING BIT OF THE KEYBOARD SCAN
  1003. REGISTER WILL BE FORCED TO "0", REGARDLESS OF WHICH KEYS ARE PRESSED AND
  1004. REGARDLESS OF WHICH SCAN ROW IS SELECTED.  ╘HERE'S THE CATCH.  ╔F WE WERE TO
  1005. UN-SELECT ALL SCAN ROWS AND STILL NOTICE "0"S IN THE KEYBOARD READ REGISTER,
  1006. THEN WE WOULD KNOW THAT THE JOYSTICK WAS BEING PUSHED AND WOULD INTERFERE WITH
  1007. OUR KEYBOARD SCANNING, SO WE COULD ABORT KEYBOARD SCANNING AND HANDLE THIS
  1008. CASE AS IF NO KEYS WERE BEING HELD DOWN.
  1009.  
  1010. ╔T STILL WOULD BE POSSIBLE BUT UNLIKELY THAT THE USER COULD PUSH THE JOYSTICK
  1011. IN THE MIDDLE OF US SCANNING THE KEYBOARD AND SCREW UP OUR RESULTS, SO TO
  1012. DEFEND AGAINST THIS, WE CHECK FOR THE JOYSTICK BEING PUSHED BOTH BEFORE AND
  1013. AFTER SCANNING THE KEYBOARD.  ╔F WE FIND THAT THE JOYSTICK IS PUSHED AT EITHER
  1014. OF THESE TIMES, THEN WE THROW OUT THE RESULTS AND ASSUME THAT NO KEYS ARE HELD
  1015. DOWN.  ╘HIS WAY, THE ONLY WAY THAT A USER COULD SCREW UP THE SCANNING IS IF
  1016. HE/SHE/IT WERE TO PRESS A SWITCH AFTER WE BEGIN SCANNING AND RELEASE IT BEFORE
  1017. WE FINISH SCANNING.  ╬OT BLOODY LIKELY FOR A HUMAN.
  1018.  
  1019. ┘OU GET THE SAME DEAL FOR KEYBOARD SCANNING ON THE 64, EXCEPT YOU ONLY NEED TO
  1020. USE $─├00 FOR SELECTING THE SCAN ROWS.  ┴LSO NOTE THAT YOU WILL NOT BE ABLE TO
  1021. PLAY WITH KEYBOARD SCANNING FROM ┬┴╙╔├ BECAUSE OF THE INTERRUPT READING OF THE
  1022. KEYBOARD.  ┘OU MUST MAKE SURE THAT INTERRUPTS ARE DISABLED WHEN PLAYING WITH
  1023. THE KEYBOARD HARDWARE, OR INTERRUPT SCANNING CAN COME ALONG AT ANY TIME AND
  1024. CHANGE ALL OF THE REGISTER SETTINGS.
  1025.  
  1026. 3.3. ╙├┴╬╬╔╬╟ ╙╧╒╥├┼ ├╧─┼
  1027.  
  1028. ╘HE FOUR KEYBOARD SCANNING TECHNIQUES OF THE EXAMPLE PROGRAM ARE PRESENTED
  1029. BELOW.  ╘HE DECLARATIONS REQUIRED FOR ALL OF THEM ARE:
  1030.  
  1031. PA = $DC00        ;ROW SELECT
  1032. PB = $DC01        ;COLUMN READ
  1033. DDRA = $DC02      ;DDR FOR ROW SELECT
  1034. DDRB = $DC03      ;DDR FOR COLUMN READ
  1035. SCAN╘ABLE .BUF 8  ;STORAGE FOR SCAN
  1036. MASK = $03        ;WORK LOCATION
  1037.  
  1038. ╘HE CODE IS AS FOLLOWS, IN ┬UDDY FORMAT.  ┼ACH ROUTINE SCANS THE KEYBOARD AND
  1039. STORES THE RESULTS IN THE "SCAN╘ABLE" TABLE.
  1040.  
  1041. ------------------+------------------+------------------+------------------+
  1042.  ╥OW FORWARD FAST ▄ ╥OW BACKWARD FAST▄ ├OLUMN RIGHT     ▄ ╥OW FORWARD SLOW
  1043. ------------------+------------------+------------------+------------------+
  1044.   SEI             ▄  SEI             ▄  SEI             ▄  SEI
  1045.   LDX #0          ▄  LDX #7          ▄  LDA #$00        ▄  LDX #0
  1046.   LDA #$FE        ▄  LDA #$7F        ▄  STA DDRA        ▄  LDA #$FE
  1047.   STA PA          ▄  STA PA          ▄  LDA #$FF        ▄  STA MASK
  1048.   NEXT╥OW = *     ▄  NEXT╥OW = *     ▄  STA DDRB        ▄  NEXT╥OW = *
  1049. - LDA PB          ▄- LDA PB          ▄  LDY #7          ▄  LDA MASK
  1050.   CMP PB          ▄  CMP PB          ▄  LDA #$7F        ▄  STA PA
  1051.   BNE -           ▄  BNE -           ▄  STA MASK        ▄- LDA PB
  1052.   EOR #$FF        ▄  EOR #$FF        ▄  NEXT├OL = *     ▄  CMP PB
  1053.   STA SCAN╘ABLE,X ▄  STA SCAN╘ABLE,X ▄  LDA MASK        ▄  BNE -
  1054.   SEC             ▄  SEC             ▄  STA PB          ▄  EOR #$FF
  1055.   ROL PA          ▄  ROR PA          ▄- LDA PA          ▄  STA SCAN╘ABLE,X
  1056.   INX             ▄  DEX             ▄  CMP PA          ▄  SEC
  1057.   CPX #8          ▄  BPL NEXT╥OW     ▄  BNE -           ▄  ROL MASK
  1058.   BCC NEXT╥OW     ▄  CLI             ▄  LDX #$FF        ▄  INX
  1059.   CLI             ▄  RTS             ▄  STX PB          ▄  CPX #8
  1060.   RTS             ▄                  ▄  EOR #$FF        ▄  BCC NEXT╥OW
  1061. ------------------+------------------+  LDX #7          ▄  CLI
  1062.                                      ▄- ASL             ▄  RTS
  1063. ╘HE FORWARD "QUICK" SCANNING STORES  ▄  ROL SCAN╘ABLE,X +------------------+
  1064. THE SCAN ROW SELECTION MASK INTO     ▄  DEX             ▄
  1065. THE ROW SELECTION REGISTER AND       ▄  BPL -           ▄
  1066. SHIFTS THE "0" BIT ONE POSITION      ▄  SEC             ▄
  1067. "FORWARD" FOR EACH ROW, DIRECTLY,    ▄  ROR MASK        ▄
  1068. USING A "ROL $DC00" INSTRUCTION.     ▄  DEY             ▄
  1069. ╘HIS WOULD PROBABLY BE THE OBVIOUS   ▄  BPL NEXT├OL     ▄
  1070. SOLUTION TO AN OPTIMIZING ASSEMBLER  ▄  LDA #$FF        ▄
  1071. PROGRAMMER.  ╚OWEVER, FOR SOME       ▄  STA DDRA        ▄
  1072. REASON NOT QUITE UNDERSTOOD BY THIS  ▄  LDA #$00        ▄
  1073. AUTHOR, THERE ARE "SHADOWING"        ▄  STA DDRB        ▄
  1074. PROBLEMS WITH THIS APPROACH.  ╔F     ▄  CLI             ▄
  1075. YOU WERE TO HOLD DOWN THE TWO KEYS   ▄  RTS             ▄
  1076. "╚" AND "╦" AT THE SAME TIME, YOU    +------------------+
  1077. WOULD NOTICE THAT THESE TWO KEYS
  1078. ARE ON THE SAME COLUMN OF TWO SUCCESSIVE ROWS.  ╔F YOU HOLD THEM BOTH DOWN,
  1079. YOU WILL SEE THE TWO POSITIONS BECOME ACTIVE, BUT SO WILL THE SAME COLUMN OF
  1080. ALL SUCCESSIVE ROWS AFTER THE "╚" AND "╦", EVEN THOUGH THESE OTHER KEYS ARE
  1081. NOT ACTUALLY HELD DOWN.  ┘OU WILL GET AN INACCURATE READING IF BAD KEYS ARE
  1082. HELD DOWN SIMULTANEOUSLY.  ┘OU WILL NOTICE THE USE OF THE TERM "ACTIVE" ABOVE.
  1083. ╘HIS IS BECAUSE ALTHOUGH THE HARDWARE RETURNS A "0" FOR ACTIVE, THE ROUTINE
  1084. CONVERTS THAT INTO A "1" FOR EASIER PROCESSING LATER.  ╔ AM NOT SURE IF
  1085. EVERYONE WILL GET THIS SAME RESULT, BUT IF YOUR KEYBOARD IS WIRED THE SAME AS
  1086. MINE, YOU WILL.
  1087.  
  1088. ╘HE BACKWARD "QUICK" SCANNING OPERATES QUITE SIMILARLY TO THE FORWARD
  1089. SCANNING, EXCEPT FOR THE DIRECTION OF THE SCAN AND THE DIRECTION OF THE
  1090. "SHADOW"; THE SHADOW GOES UPWARDS.  ┘OU MIGHT THINK THAT ┴╬─ING TOGETHER THE
  1091. RESULTS OF THE FORWARD AND BACKWARD SCAN TOGETHER WOULD ELIMINATE THE SHADOW,
  1092. BUT THIS WILL NOT WORK SINCE ANY ROWS BETWEEN THE ROWS CONTAINING THE TWO KEYS
  1093. HELD DOWN WILL BE INCORRECTLY READ AS BEING ACTIVE.
  1094.  
  1095. ╘HE COLUMNWISE RIGHT SCANNING IS THE MOST COMPLICATED BECAUSE THE ROWS MUST BE
  1096. CONVERTED INTO COLUMNS, TO ALLOW THE SCAN MATRIX TO BE INTERPRETED AS BEFORE.
  1097. ┴LSO, THE ─ATA ─IRECTION ╥EGISTERS HAVE TO BE CHANGED.  ┘OU MIGHT THINK THAT
  1098. COMBINGING ROW-WISE SCANNING WITH COLUMNWISE SCANNING WOULD GIVE BETTER
  1099. RESULTS, AND IT PROBABLY WOULD, IF IT WEREN'T FOR A BIZARRE HARDWARE PROBLEM.
  1100. ╔F YOU HOLD DOWN TWO OR MORE KEYS ON THE SAME SCAN ROW, SAY "╫" AND "┼", SOME
  1101. OF THE KEYS WILL FLICKER OR DISAPPEAR, GIVING AN INACCURATE READING.
  1102.  
  1103. ╘HE FORWARD "SLOW" SCANNING IS THE BEST OF THE BUNCH.  ╔NCIDENTALLY, IT IS
  1104. WHAT THE ╦ERNAL USES (AS NEAR AS ╔ CAN FIGURE - THEIR CODE IS EXTREMELY
  1105. CONVOLUTED).  ╘HIS TECHNIQUE IS THE SAME AS THE FORWARD "QUICK SCAN," EXCEPT
  1106. THAT THE ROW SELECTION MASK IS SHIFTED IN A WORKING STORAGE LOCATION AND POKED
  1107. INTO THE ├╔┴ REGISTER, RATHER THAN BEING SHIFTED IN PLACE.  ╔ DON'T KNOW WHY
  1108. THIS MAKES A DIFFERENCE, BUT IT DOES.  ╘HERE IS STILL A PROBLEM WITH THIS
  1109. TECHNIQUE, BUT THIS PROBLEM OCCURS WITH ALL TECHNIQUES.  ╔F YOU HOLD DOWN
  1110. THREE KEYS THAT FORM THREE "CORNERS" OF A RECTANGLE IN THE SCANNING MATRIX,
  1111. THEN THE MISSING CORNER WILL BE READ AS BEING HELD DOWN ALSO.  ╞OR EXAMPLE, IF
  1112. YOU HOLD DOWN "├", "╬", AND "═", THEN THE KEYBOARD HARDWARE WILL ALSO THINK
  1113. THAT YOU ARE HOLDING DOWN THE "╪" KEY.  ╘HIS IS WHY THIS ARTICLE IMPLEMENTS A
  1114. "THREE-KEY" ROLLOVER RATHER THAN AN "╬-KEY" ROLLOVER.  ═ANY THREE-KEY
  1115. COMBINATIONS WILL STILL BE INTERPRETED CORRECTLY.  ╬OTE, HOWEVER, THAT SHIFT
  1116. KEYS SUCH AS ╙╚╔╞╘ OR ├╧╬╘╥╧╠ WILL ADD ONE MORE KEY TO THE HARDWARE SCANNING
  1117. (BUT WILL NOT BE COUNTED IN THE THREE-KEY ROLLOVER), MAKING INACCURATE RESULTS
  1118. MORE LIKELY IF YOU ARE HOLDING DOWN MULTIPLE OTHER KEYS AT THE SAME TIME.
  1119.  
  1120. 4. ╘╚┼ ├-128 ╦┼┘╙├┴╬╬┼╥
  1121.  
  1122. ╘HIS SECTION GIVES THE SOURCE CODE FOR THE ├-128 IMPLEMENTATION OF THE
  1123. THREE-KEY ROLLOVER.  ╘HE FORWARD "SLOW" KEY MATRIX SCANNING TECHNIQUE IS USED,
  1124. EXTENDED TO WORK WITH THE EXTRA KEYS OF THE 128.  ╔T WAS A BIT OF A PAIN
  1125. WEDGING INTO THE ╦ERNAL, SINCE THERE IS NOT A CONVENIENT INDIRECT ╩═╨ INTO
  1126. SCANNING THE KEYBOARD, LIKE THERE ARE FOR DECODING AND BUFFERING PRESSED KEYS.
  1127. ┴ RATHER LENGTHY ╔╥╤ "PREAMBLE" HAD TO BE COPIED FROM THE ╥╧═, UP TO THE
  1128. POINT WHERE IT ╩╙╥S TO THE KEYSCANNING ROUTINE.  ╘HIS CODE IN INCLUDED IN
  1129. THE FORM OF A ".BYTE" TABLE, TO SPARE YOU THE DETAILS.
  1130.  
  1131. ┬EFORE SCANNING THE KEYBOARD, WE CHECK TO SEE IF JOYSTICK #1 IS PUSHED AND IF
  1132. A KEY IS ACTUALLY PRESSED.  ╔F NOT, WE ABORT SCANNING AND ╩═╨ TO THE KEY
  1133. REPEAT HANDLING IN THE ╥╧═.  ╔F A KEY IS HELD DOWN, WE SCAN THE KEYBOARD AND
  1134. THEN EXAMINE THE RESULT.  ╞IRST WE CHECK FOR THE SHIFT KEYS (╙╚╔╞╘, ├╧══╧─╧╥┼,
  1135. ├╧╬╘╥╧╠, ┴╠╘, AND ├┴╨╙ ╠╧├╦), PUT THEM INTO LOCATION $─3 (SHIFT FLAGS) IN BIT
  1136. POSTITIONS 1, 2, 4, 8, AND 16, RESPECTIVELY, AND REMOVE THEM FROM THE SCAN
  1137. MATRIX.  ╘HE ├┴╨╙ ╠╧├╦ KEY IS NOT ON THE MAIN KEY MATRIX; IT IS READ FROM THE
  1138. PROCESSOR ╔/╧ PORT.  ╘HIS IS GOOD, BECAUSE OTHERWISE WE COULD NOT ABORT
  1139. SCANNING IF IT WERE THE ONLY KEY HELD DOWN.
  1140.  
  1141. ╘HEN WE SCAN THE KEYMATRIX FOR THE FIRST THREE KEYS THAT ARE BEING HELD DOWN,
  1142. OR AS MANY AS ARE HELD DOWN IF LESS THAN THREE.  ╫E STORE THE SCAN CODES OF
  1143. THESE KEYS INTO A 3-ELEMENT ARRAY.  ╫E ALSO RETAIN A COPY OF THE 3-ELEMENT
  1144. ARRAY FROM THE PREVIOUS SCAN AND WE CHECK FOR DIFFERENT KEYS BEING IN THE TWO
  1145. ARRAYS.  ╔F THE OLD ARRAY CONTAINS A KEY THAT IS NOT PRESENT IN THE NEW ARRAY,
  1146. THEN THE USE HAS RELEASED A KEY, SO WE SET A FLAG TO INHIBIT INTERPRETATION OF
  1147. KEYS AND PRETEND THAT NO KEYS ARE HELD DOWN.  ╘HIS IS TO ELIMINATE UNDESIRABLE
  1148. EFFECTS OF HAVING OTHER KEYS HELD DOWN REPEAT IF YOU RELEASE THE MOST RECENTLY
  1149. PUSHED KEY FIRST.  ╨├ KEYBOARDS DO THIS.  ╘HIS INHIBITING WILL BE IGNORED IF
  1150. NEW KEYS ARE DISCOVERED IN THE NEXT STEP.
  1151.  
  1152. ╔F THERE ARE KEYS IN THE NEW ARRAY THAT ARE NOT IN THE OLD, THEN THE USER HAS
  1153. JUST PRESSED A NEW KEY, SO THAT NEW KEY GOES TO THE HEAD OF THE OLD ARRAY AND
  1154. WE STOP COMPARING THE ARRAYS THERE.  ╘HE KEY IN THE FIRST POSITION OF THE OLD
  1155. ARRAY IS POKED INTO THE ╦ERNAL "KEY HELD DOWN" LOCATION FOR THE ╦ERNAL TO
  1156. INTERPRET LATER.  ╔F MORE THAN ONE NEW KEY IS DISCOVERED AT THE SAME TIME,
  1157. THEN EACH OF THE NEW KEYS WILL BE PICKED UP ON SUCCESSIVE KEYBOARD SCANS AND
  1158. WILL BE INTERPRETED AS JUST BEING PUSHED.  ╙O, IF YOU PRESS THE "┴", "╬", AND
  1159. "─" KEYS ALL AT THE SAME TIME, SOME PERMUTATION OF ALL THREE OF THESE KEYS
  1160. WILL APPEAR ON THE SCREEN.
  1161.  
  1162. ╫HEN WE ARE DONE INTERPRETING THE KEYS, WE CHECK THE JOYSTICK ONCE MORE AND IF
  1163. IT IS STILL INACTIVE, WE PRESENT THE MOST RECENTLY PUSHED DOWN KEY TO THE
  1164. ╦ERNAL AND ╩═╨ INTO THE ╥╧═ KEYBOARD DECODING ROUTINE.
  1165.  
  1166. ╒NLIKE IN PREVIOUS ISSUES, THIS SOURCE CODE IS HERE IN LITERAL FORM; JUST
  1167. EXTRACT EVERYTHING BETWEEN THE "-----=-----"S TO NAB THE SOURCE FOR YOURSELF.
  1168. ╘HE SOURCE IS IN ┬UDDY ASSEMBLER FORMAT.
  1169.  
  1170. -----=-----
  1171. ;3-╦EY ╥OLLOVER-128 BY ├RAIG ┬RUCE 18-╩UN-93 FOR ├= ╚ACKING MAGAZINE
  1172.  
  1173. .ORG $1500
  1174. .OBJ "@0:KEYSCAN128"
  1175.  
  1176. SCANROWS = 11
  1177. ROLLOVER = 3
  1178.  
  1179. PA = $DC00
  1180. PB = $DC01
  1181. PK = $D02F
  1182.  
  1183. JMP INITIAL╔NSTALL
  1184.  
  1185. ;UGLY ╔╥╤ PATCH CODE.
  1186.  
  1187. IRQ = *  ;$1503
  1188.    .BYTE $D8,$20,$0A,$15,$4C,$69,$FA,$38,$AD,$19,$D0,$29,$01,$F0,$07,$8D
  1189.    .BYTE $19,$D0,$A5,$D8,$C9,$FF,$F0,$6F,$2C,$11,$D0,$30,$04,$29,$40,$D0
  1190.    .BYTE $31,$38,$A5,$D8,$F0,$2C,$24,$D8,$50,$06,$AD,$34,$0A,$8D,$12,$D0
  1191.    .BYTE $A5,$01,$29,$FD,$09,$04,$48,$AD,$2D,$0A,$48,$AD,$11,$D0,$29,$7F
  1192.    .BYTE $09,$20,$A8,$AD,$16,$D0,$24,$D8,$30,$03,$29,$EF,$2C,$09,$10,$AA
  1193.    .BYTE $D0,$28,$A9,$FF,$8D,$12,$D0,$A5,$01,$09,$02,$29,$FB,$05,$D9,$48
  1194.    .BYTE $AD,$2C,$0A,$48,$AD,$11,$D0,$29,$5F,$A8,$AD,$16,$D0,$29,$EF,$AA
  1195.    .BYTE $B0,$08,$A2,$07,$CA,$D0,$FD,$EA,$EA,$AA,$68,$8D,$18,$D0,$68,$85
  1196.    .BYTE $01,$8C,$11,$D0,$8E,$16,$D0,$B0,$13,$AD,$30,$D0,$29,$01,$F0,$0C
  1197.    .BYTE $A5,$D8,$29,$40,$F0,$06,$AD,$11,$D0,$10,$01,$38,$58,$90,$07,$20
  1198.    .BYTE $AA,$15,$20,$E7,$C6,$38,$60
  1199.  
  1200. ;KEYSCANNING ENTRY POINT
  1201.  
  1202. MAIN = *
  1203.    LDA #0               ;CHECK IF ANY KEYS ARE HELD DOWN
  1204.    STA PA
  1205.    STA PK
  1206. -  LDA PB
  1207.    CMP PB
  1208.    BNE -
  1209.    CMP #$FF
  1210.    BEQ NO╦EY╨RESSED     ;IF NOT, THEN DON'T SCAN KEYBOARD, GOTO ╦ERNAL
  1211.  
  1212.    JSR CHECK╩OYSTICK    ;IF SO, MAKE SURE JOYSTICK NOT PRESSED
  1213.    BCC JOYSTICK╨RESSED
  1214.    JSR KEYSCAN          ;SCAN THE KEYBOARD AND STORE RESULTS
  1215.    JSR CHECK╩OYSTICK    ;MAKE SURE JOYSTICK NOT PRESSED AGAIN
  1216.    BCC JOYSTICK╨RESSED
  1217.    JSR SHIFTDECODE      ;DECODE THE SHIFT KEYS
  1218.    JSR KEYDECODE        ;DECODE THE FIRST 3 REGULAR KEYS HELD DOWN
  1219.    JSR KEYORDER         ;SEE WHICH NEW KEYS PRESSED, OLD KEYS RELEASED, AND
  1220.                         ;  DETERMINE WHICH KEY TO PRESENT TO THE ╦ERNAL
  1221.    LDA $033E            ;SET UP FOR AND DISPATCH TO ╦ERNAL
  1222.    STA $CC
  1223.    LDA $033F
  1224.    STA $CD
  1225.    LDX #$FF
  1226.    BIT IGNORE╦EYS
  1227.    BMI ++
  1228.    LDA PREV╦EYS+0
  1229.    CMP #$FF
  1230.    BNE +
  1231.    LDA $D3
  1232.    BEQ ++
  1233.    LDA #88
  1234. +  STA $D4
  1235.    TAY
  1236.    JMP ($033A)
  1237.  
  1238.    NO╦EY╨RESSED = *     ;NO KEYS PRESSED; SELECT DEFAULT SCAN ROW
  1239.    LDA #$7F
  1240.    STA PA
  1241.    LDA #$FF
  1242.    STA PK
  1243.  
  1244.    JOYSTICK╨RESSED = *
  1245.    LDA #$FF             ;RECORD THAT NO KEYS ARE DOWN IN OLD 3-KEY ARRAY
  1246.    LDX #ROLLOVER-1
  1247. -  STA PREV╦EYS,X
  1248.    DEX
  1249.    BPL -
  1250.    JSR SCAN├APS         ;SCAN THE ├┴╨╙ ╠╧├╦ KEY
  1251.    LDX #$FF
  1252.    LDA #0
  1253.    STA IGNORE╦EYS
  1254.  
  1255. +  LDA #88              ;PRESENT "NO KEY HELD" TO ╦ERNAL
  1256.    STA $D4
  1257.    TAY
  1258.    JMP $C697
  1259.  
  1260. INITIAL╔NSTALL = *      ;INSTALL WEDGE: SET RESTORE VECTOR, PRINT MESSAGE
  1261.    JSR INSTALL
  1262.    LDA #<REINSTALL
  1263.    LDY #>REINSTALL
  1264.    STA $0A00
  1265.    STY $0A01
  1266.    LDX #0
  1267. -  LDA INSTALL═SG,X
  1268.    BEQ +
  1269.    JSR $FFD2
  1270.    INX
  1271.    BNE -
  1272. +  RTS
  1273.  
  1274.    INSTALL═SG = *
  1275.    .BYTE 13
  1276.    .ASC "KEYSCAN128 INSTALLED"
  1277.    .BYTE 0
  1278.  
  1279. REINSTALL = *           ;RE-INSTALL WEDGE AFTER A ╥╒╬/╙╘╧╨+╥┼╙╘╧╥┼
  1280.    JSR INSTALL
  1281.    JMP $4003
  1282.  
  1283. INSTALL = *             ;GUTS OF INSTALLATION: SET ╔╥╤ VECTOR TO PATCH CODE
  1284.    SEI                  ;  AND INITIALIZE SCANNING VARIABLES
  1285.    LDA #<IRQ
  1286.    LDY #>IRQ
  1287.    STA $0314
  1288.    STY $0315
  1289.    CLI
  1290.    LDX #ROLLOVER-1
  1291.    LDA #$FF
  1292. -  STA PREV╦EYS,X
  1293.    DEX
  1294.    BPL -
  1295.    LDA #0
  1296.    STA IGNORE╦EYS
  1297.    RTS
  1298.  
  1299. MASK = $CC
  1300.  
  1301. KEYSCAN = *             ;SCAN THE (EXTENDED) KEYBOARD USING THE FORWARD
  1302.    LDX #$FF             ;  ROW-WISE "SLOW" TECHNIQUE
  1303.    LDY #$FF
  1304.    LDA #$FE
  1305.    STA MASK+0
  1306.    LDA #$FF
  1307.    STA MASK+1
  1308.    JMP +
  1309.    NEXT╥OW = *
  1310. -  LDA PB
  1311.    CMP PB
  1312.    BNE -
  1313.    STY PA
  1314.    STY PK
  1315.    EOR #$FF
  1316.    STA SCAN╘ABLE,X
  1317.    SEC
  1318.    ROL MASK+0
  1319.    ROL MASK+1
  1320. +  LDA MASK+0
  1321.    STA PA
  1322.    LDA MASK+1
  1323.    STA PK
  1324.    INX
  1325.    CPX #SCANROWS
  1326.    BCC NEXT╥OW
  1327.    RTS
  1328.  
  1329. SHIFT╓ALUE = $D3
  1330.  
  1331. SHIFT╥OWS .BYTE $01,$06,$07,$07,$0A
  1332. SHIFT┬ITS .BYTE $80,$10,$20,$04,$01
  1333. SHIFT═ASK .BYTE $01,$01,$02,$04,$08
  1334.  
  1335. SHIFTDECODE = *         ;SEE WHICH "SHIFT" KEYS ARE HELD DOWN, PUT THEM INTO
  1336.    JSR SCAN├APS         ;  PROPER POSITIONS IN $─3 (SHIFT FLAGS), AND REMOVE
  1337.    LDY #4               ;  THEM FROM THE SCAN MATRIX
  1338. -  LDX SHIFT╥OWS,Y
  1339.    LDA SCAN╘ABLE,X
  1340.    AND SHIFT┬ITS,Y
  1341.    BEQ +
  1342.    LDA SHIFT═ASK,Y
  1343.    ORA SHIFT╓ALUE
  1344.    STA SHIFT╓ALUE
  1345.    LDA SHIFT┬ITS,Y
  1346.    EOR #$FF
  1347.    AND SCAN╘ABLE,X
  1348.    STA SCAN╘ABLE,X
  1349. +  DEY
  1350.    BPL -
  1351.    RTS
  1352.  
  1353. SCAN├APS = *            ;SCAN THE ├┴╨╙ ╠╧├╦ KEY FROM THE PROCESSOR ╔/╧ PORT
  1354. -  LDA $1
  1355.    CMP $1
  1356.    BNE -
  1357.    EOR #$FF
  1358.    AND #$40
  1359.    LSR
  1360.    LSR
  1361.    STA SHIFT╓ALUE
  1362.    RTS
  1363.  
  1364. NEWPOS = $CC
  1365. KEYCODE = $D4
  1366. XSAVE = $CD
  1367.  
  1368. KEYDECODE = *           ;GET THE SCAN CODES OF THE FIRST THREE KEYS HELD DOWN
  1369.    LDX #ROLLOVER-1      ;INITIALIZE: $FF MEANS NO KEY HELD
  1370.    LDA #$FF
  1371. -  STA NEW╦EYS,X
  1372.    DEX
  1373.    BPL -
  1374.    LDY #0
  1375.    STY NEWPOS
  1376.    LDX #0
  1377.    STX KEYCODE
  1378.  
  1379.    DECODE╬EXT╥OW = *    ;DECODE A ROW, INCREMENTING THE CURRENT SCAN CODE
  1380.    LDA SCAN╘ABLE,X
  1381.    BEQ DECODE├ONTINUE
  1382.                         ;AT THIS POINT, WE KNOW THAT THE ROW HAS A KEY HELD
  1383.    LDY KEYCODE
  1384. -  LSR
  1385.    BCC ++
  1386.    PHA                  ;HERE WE KNOW WHICH KEY IT IS, SO STORE ITS SCAN CODE,
  1387.    STX XSAVE            ;  UP TO 3 KEYS
  1388.    LDX NEWPOS
  1389.    CPX #ROLLOVER
  1390.    BCS +
  1391.    TYA
  1392.    STA NEW╦EYS,X
  1393.    INC NEWPOS
  1394. +  LDX XSAVE
  1395.    PLA
  1396. +  INY
  1397.    CMP #$00
  1398.    BNE -
  1399.  
  1400.    DECODE├ONTINUE = *
  1401.    CLC
  1402.    LDA KEYCODE
  1403.    ADC #8
  1404.    STA KEYCODE
  1405.    INX
  1406.    CPX #SCANROWS
  1407.    BCC DECODE╬EXT╥OW
  1408.    RTS
  1409.  
  1410. ;KEYORDER: DETERMINE WHAT KEY TO PRESENT TO THE ╦ERNAL AS BEING LOGICALLY THE
  1411. ;ONLY ONE PRESSED, BASED ON WHICH KEYS PREVIOUSLY HELD HAVE BEEN RELEASED AND
  1412. ;WHICH NEW KEYS HAVE JUST BEEN PRESSED
  1413.  
  1414. KEYORDER = *
  1415.    ;** REMOVE OLD KEYS NO LONGER HELD FROM OLD SCAN CODE ARRAY
  1416.    LDY #0
  1417.    NEXT╥EMOVE = *
  1418.    LDA PREV╦EYS,Y       ;GET CURRENT OLD KEY
  1419.    CMP #$FF
  1420.    BEQ ++
  1421.    LDX #ROLLOVER-1      ;SEARCH FOR IT IN THE NEW SCAN CODE ARRAY
  1422. -  CMP NEW╦EYS,X
  1423.    BEQ +
  1424.    DEX
  1425.    BPL -
  1426.    TYA                  ;HERE, OLD KEY NO LONGER HELD; REMOVE IT
  1427.    TAX
  1428. -  LDA PREV╦EYS+1,X
  1429.    STA PREV╦EYS+0,X
  1430.    INX
  1431.    CPX #ROLLOVER-1
  1432.    BCC -
  1433.    LDA #$FF
  1434.    STA PREV╦EYS+ROLLOVER-1
  1435.    STA IGNORE╦EYS
  1436. +  INY                  ;CHECK NEXT OLD KEY
  1437.    CPY #ROLLOVER
  1438.    BCC NEXT╥EMOVE
  1439.  
  1440.    ;** INSERT NEW KEYS AT FRONT OF OLD SCAN CODE ARRAY 
  1441. +  LDY #0
  1442.    NEXT╔NSERT = *
  1443.    LDA NEW╦EYS,Y        ;GET CURRENT NEW KEY
  1444.    CMP #$FF
  1445.    BEQ ++
  1446.    LDX #ROLLOVER-1      ;CHECK OLD SCAN CODE ARRAY FOR IT
  1447. -  CMP PREV╦EYS,X
  1448.    BEQ +
  1449.    DEX
  1450.    BPL -
  1451.    PHA                  ;IT'S NOT THERE, SO INSERT NEW KEY AT FRONT, EXIT
  1452.    LDX #ROLLOVER-2
  1453. -  LDA PREV╦EYS+0,X
  1454.    STA PREV╦EYS+1,X
  1455.    DEX
  1456.    BPL -
  1457.    LDA #0
  1458.    STA IGNORE╦EYS
  1459.    PLA
  1460.    STA PREV╦EYS+0
  1461.    LDY #ROLLOVER        ;(TRICK TO EXIT)
  1462. +  INY
  1463.    CPY #ROLLOVER
  1464.    BCC NEXT╔NSERT
  1465. +  RTS                  ;NOW, THE HEAD OF THE OLD SCAN CODE ARRAY CONTAINS
  1466.                         ;  THE SCAN CODE TO PRESENT TO THE ╦ERNAL, AND OTHER
  1467.                         ;  POSITIONS REPRESENT KEYS THAT ARE ALSO HELD DOWN
  1468.                         ;  THAT HAVE ALREADY BEEN PROCESSED AND THEREFORE CAN
  1469.                         ;  BE IGNORED UNTIL THEY ARE RELEASED
  1470.  
  1471. CHECK╩OYSTICK = *       ;CHECK IF JOYSTICK IS PUSHED: UN-SELECT ALL KEYBOARD
  1472.    LDA #$FF             ;  ROWS AND SEE IF THERE ARE ANY "0"S IN THE SCAN
  1473.    STA PA               ;  STATUS REGISTER
  1474.    STA PK
  1475. -  LDA PB
  1476.    CMP PB
  1477.    BNE -
  1478.    CMP #$FF
  1479.    LDA #$7F             ;RESTORE TO DEFAULT ╦ERNAL ROW SELECTED (TO THE ONE
  1480.    STA PA               ;  CONTAINING THE ╙╘╧╨ KEY)
  1481.    LDA #$FF
  1482.    STA PK
  1483.    RTS
  1484.  
  1485. ;GLOBAL VARIABLES
  1486.  
  1487. SCAN╘ABLE  .BUF SCANROWS        ;VALUES OF THE ELEVEN KEYBOARD SCAN ROWS
  1488. NEW╦EYS    .BUF ROLLOVER        ;CODES OF UP TO THREE KEYS HELD SIMULTANEOUSLY
  1489. IGNORE╦EYS .BUF 1               ;FLAG: IF AN OLD KEY HAS BEEN RELEASED AND NO
  1490.                                 ;  NEW KEY HAS BEEN PRESSED, STOP ALL KEY
  1491.                                 ;  REPEATING
  1492. PREV╦EYS   .BUF ROLLOVER+2      ;KEYS HELD ON PREVIOUS SCAN
  1493. -----=-----
  1494.  
  1495. ┴ND THAT'S ALL THERE IS TO IT.  :-)
  1496.  
  1497. 5. ╘╚┼ ├-64 ╦┼┘╙├┴╬╬┼╥
  1498.  
  1499. ╘HE BOOT PROGRAM FOR THE ├-64 KEYSCANNER IS AS FOLLOWS:
  1500.  
  1501. 10 D=PEEK(186)
  1502. 20 IF A=1 THEN 60
  1503. 30 A=1
  1504. 40 LOAD"KEYSCAN64",D,1
  1505. 50 GOTO 10
  1506. 60 SYS 49152+5*256  : REM $C500
  1507.  
  1508. ╔T IS VERY MUCH LIKE BOOT PROGRAMS FOR OTHER MACHINE LANGUAGE PROGRAMS THAT
  1509. DON'T LOAD AT THE START OF ┬┴╙╔├.  ╔T WILL LOAD THE BINARY FROM THE LAST
  1510. DEVICE ACCESSED, AND ACTIVATE IT.
  1511.  
  1512. ┴ LISTING OF THE ├-64 KEYSCANNING CODE IS NOT PRESENTED HERE BECAUSE IT IS SO
  1513. SIMILAR TO THE ├-128 LISTING.  ╘HE ONLY THINGS THAT ARE DIFFERENT ARE THE
  1514. ╦ERNAL PATCHES AND THE KEYBOARD SCANNING (BECAUSE THE THREE EXTRA ROWS DON'T
  1515. HAVE TO BE SCANNED).  ╘HE ╔╥╤ HAD TO BE SUBSTANTIALLY COPIED FROM THE ╥╧═,
  1516. AGAIN, TO GET AT THE CALL TO THE KEY SCANNING.  ┴LSO, RATHER THAN TAKING
  1517. OVER THE ┬┴╙╔├ RESET VECTOR (SINCE THERE ISN'T ONE), THE ╬═╔ VECTOR IS
  1518. TAKEN OVER TO INSURE THE SURVIVAL OF THE KEY SCANNER AFTER A ╥╒╬/╙╘╧╨+╥┼╙╘╧╥┼.
  1519. ┴ BIT OF ITS PREAMBLE ALSO HAD TO BE COPIED OUT OF ╥╧═ TO GET AT THE GOOD
  1520. STUFF.  ╔F YOU WANT A COPY OF THE ├-64 LISTING, YOU CAN E-MAIL ME.
  1521.  
  1522. 6. ╒╒┼╬├╧─┼─ ╞╔╠┼╙
  1523.  
  1524. ╚ERE ARE THE BINARY EXECUTABLES IN UUENCODED FORM.  ╘HE ├╥├32S OF THE FOUR
  1525. FILES ARE AS FOLLOWS:
  1526.  
  1527. CRC32 = 3398956287 FOR "KEYSCAN128"
  1528. CRC32 = 2301926894 FOR "KEYSCAN64.BOOT"
  1529. CRC32 = 1767081474 FOR "KEYSCAN64"
  1530. CRC32 = 1604419896 FOR "KEYSHOW"
  1531.  
  1532. BEGIN 640 KEYSCAN128
  1533. ═└!5,'┴;8(└╚53&╟┌.*╘9╘"─!\└>-&="┼╓,╟_\&\╠$=└╨!"┼└╘#$╪╔=├╨+"38
  1534. ═4└:═-└╩-$═"┼└2╟]"01(╦2╘*2*╘1╘"┼_"2"╚╦1;0)-@╨└╥╟╧+└─0╩═└╚╩?^-
  1535. ═$═"┼└0─"*?╠%╓4┬═+└╔(╦1'0*5^╚╦1;0*>^╩╠└┬┬!\╦0_>╦╩╩╞┬-&-!╚┴0&,
  1536. ═$=".%═"╨$┌╘╨╘"─!\└╥┼╓"┼└\└:═$=└0└3┴8─└<@╩┴4@┘\8╪8*─└├0#<├2_0
  1537. ═╦0'<╙0'<╘/├)__└┌((─7─#\@<18@┬1>0-╥"╫%┬#╠%┬└╠%┌╘^└╪7,╦3\#┴<╓┬
  1538. ═_╥╥╘%╙└╤╦;47╥?_0!╩73\":╔6(74╩&╨┌└┌┼_├0#<╩?^-+]"╔_┌("╟;47╥┴#┌
  1539. ═(-╘6╚╧^╔└(╓╘%┌┼8┴=2╚3)?&(%46╩4^@%╚╘└"╚╨!"╩(└╧3─6\└8@╘╧_╚╘/5@
  1540. ═#4═%65-#04╪╤,├@@24┘35$%,3$5$└"!5%─╨#0'┬╔└┌└5├10#├!4#6*("╩?^=
  1541. ══1?*$/╩╔└(╓╘%╓"┬_┌#_╩?┌%╙*╟_┴<╒,╞!:═└=╙-└=╙0^(╨└╫(╨╧╘$╟_╟:87
  1542. ═.";,)╠╓┼╙(╘└╫*7-├2_0┌.└+─-┼@└08'!╨╩└$"└$└0$!└@0((-╘6╚└2^╩!:]
  1543. ═╔┴<┘╦1;╨$╦╞╥%@73┴=.┘╦19)_╙╓╞%┘╓╞%╪@0╪&"┼└<4!╘/╔)_╥┼└2─╩%╘╓"┬
  1544. ═└╩╟_╟;$7╥┴#┌╚└"$╙*(└┴═2]╔┴?╨'*342╔└22(;-╔╠╙@└[└&╞)╓╤%^;,╔╠╒╚
  1545. ═╥,─└╘.88╔=1╔"(74┌.└+─--@╚└"┘═1?)__└─╚@+=╠1?╨&,╚0^)┬╩╧;87╟;47
  1546. ═┌.└"─/6╔_╪╓╫%╪╓╘%\├└└┘#5╚└"┘╠1?)__└╞╚@+=═1?╨&╠╚0^$┬┬└;╓╒%┘╓╓
  1547. ═%\╚0]┌─└├;07:(╓╒%┌└#╥,└#─--@╩?^-└-╥-+]"═└=╙-└=╙0^,╟_╩7^-└-╥╔
  1548. 9_╪╘╧╘&└└└└└└└└└└└└└└└└└└└└└└└└└└└└└└
  1549. END
  1550. BEGIN 640 KEYSCAN64.BOOT
  1551. ═└0@."└╚└1++"*#$╪-┬─└'0@4└(╠@0;(╤(*<@-├└└)0@>└$&╥,0└┌""@└─╥)+
  1552. ═15┼30╘%.-├0┬+$0╠,0!#"#(└┬2└╤,└!@"#╨└╟┬└╘.3$╒,╩╚╒╦#(╒-┬└@.┬"/
  1553. )("1#-3└╨└└└└└└└└
  1554. END
  1555. BEGIN 640 KEYSCAN64
  1556. ═└,5,╤,5,$,9,┌╠4@┌╧^┼╙-└╔╤╠╫0):─4┴<╓─╘╘;/╦╚<"╠=&╨$>;/┴<╪@).╩╤
  1557. ═\╪╓'└╩┌&└╩7.28└@'.╩┼└2─0\└╩@└(3└╔0$)(-└(╔<#0!╩4!*1^%└2!9╤4╤^
  1558. ═┌╩─└├0#<╦0'<╙0'<╘/├)__└┘(%├'─#─@6,8@6,>0,2"-╤┬"[╤┬#[╤╩╞!┴?6╔
  1559. ═┌╪7╓╚╧\╠>,<╨+:╒┘╤\╟_╘└>═├0+╨(:┼└┴<╬╚;(\"╩7^-└-╥╔_┌("╟7╟'╥┴#┌
  1560. ═(+7&╚╧^╔└(╒╪╤┌┼└┴<╬╚3";╦(.╦%╚@"]╒<7╨!┬#2_^├0]6!+15┼30╘%.-├0@
  1561. ═24┘35$%,3$5$#0!╪╩0╞@╤8╘4└╪╨5└┌─╟╚,:-&└.,&0-8╚@*╔_┘╒┘╤\╚0^╩─└
  1562. ═├7├'8'┬╔,:#╩├10#├!4#╩4>@_╚╘8└╪╨9└╒┴@2(╔(╞$┬╔?╪╘-╫:╨-╫3└?(└+]
  1563. ═╘└-╠└╚└@╧/8@╪?_0#╥└5_2"├_2└8┘2#╩╤6╨"╚$╤╥_╩+_╚/^╔_╚7╒3';&╦0'<
  1564. ═╙0'<╘/┬,└-╤)_┘╒═╤╙@╞]:7╒├0#<┌.└(─.-@└08'!╪└0(└0!└0($(+7&╚└.^
  1565. ═@<:];<<┘┴<;╨%+╞)╤@╓-└╚╓-└╦╞%╤─╟_/6╫'╟6╫'┬!#>8*─└├8╘"8*("╩?^=
  1566. ═=<?*$/╩@└(3╒╚@"&╥[╒═╤_└<╔,═*─!)(┴╧:╞]>└#╠└:8╟77'┘╧6╞]╞├(╥0#0
  1567. ═┘┴┬┼╥╓─(┴<╧╚╪└┬0╘╓"@└+┼┘╤\╟_\"2┬└═╒╒╤_└8╥┴#╪╞*╩]>╠>=><?╚╪└*0
  1568. ═]:╟_├7╧'├7├'╥,└#─-6@└+┼╒╤\╟_\":┬└═╒┘╤_└:╥┴#╪2*(!╧7╟'╟7╦'╥┴#╫
  1569. ═╩0"->,=╚├7╟'╚└/(╨└.0╘╓"╔_╪╘└╫*╘!╫,╘!╫-#╪╥?^╔?╪╘└╫&└└└└└└└└└└
  1570. *└└└└└└└└└└└└└└└└
  1571. END
  1572. BEGIN 640 KEYSHOW
  1573. ═└!-,"╤,└└└└└└└└└└*╞3(-+_(#83╚@└@%╤0@5┴.┬"┬└7%"!╘$┌(4(!<4(/03
  1574. ═╚┴╪@%╤0@3!1,$!-╪╚@"╔_╚╘└╫*╘!╫,╘!╫-#╪2?^=└╤,╪+@#<┌.└(─.╔88'┬┬
  1575. ═!┌┼_├0#<╦0'<╙0'<╘/┴)_┘╘#$╙┴╬└-╙*$.╤88'┬╔└(╘"╫*╟_├0/<╚└>╔?╪4#
  1576. ═╔0.-└=╥═└-╙-└-╙0^*+_├@'<2?^┬!╨╚^└╤/*$/─╪9@.($-╓╔_╪╘"╫*─└├0/<
  1577. ═6&!╪╩0"-└═╥╔_╪╘#╫*└'╩7^%└┌4#├0'<╦0#<╙0#<╘/┬┬_╪╪!╫$╟_╚@<*/@,3
  1578. ═╥┴#┘.&8#┬!#=╩?^-└═╥╔└(╘#╫%┴@>*(└╩?┌%└┌4#├0#<╦0'<╙0'<╘/┴)_┘╘#
  1579. ═$╙@╞└^├@")#╞6&"@!(8$┴└6┬└+╘#$╥└╓%!┬┼!&─╚┴020└╬8%┌.└(─.╔@┴0*@
  1580. 6!╘8"╩0!╔,)$$┬!#╒8└└└└└└└└*(└8└└└
  1581. END
  1582. ================================================================================
  1583. ╔N THE ╬EXT ╔SSUE:
  1584.  
  1585. ╬EXT ╔SSUE:
  1586.  
  1587. ╘ECH-TECH - MORE RESOLUTION TO VERTICAL SHIFT
  1588.  
  1589. ╧NE TIME HALF OF THE DEMOS HAD PICTURES WAVING HORIZONTALLY ON THE WIDTH
  1590. OF THE WHOLE SCREEN. ╘HIS EFFECT IS NAMED TECH-TECH AND IT IS DONE USING
  1591. CHARACTER GRAPHICS. ╚OW EXACTLY AND IS THE SAME POSSIBLE WITH SPRITES ?
  1592.  
  1593. ╘╚┼ ─┼╙╔╟╬ ╧╞ ┴├┼-128/64
  1594.  
  1595. ─ESIGN OF ┴├┼-128/64 COMMAND SHELL ENVIRONMENT (AND KERNEL REPLACEMENT).  ╘HIS
  1596. WILL COVER THE ORGANIZATION, INTERNAL OPERATION, AND THE KERNEL INTERFACE OF
  1597. THE STILL-UNDER-DEVELOPMENT BUT POSSIBLY CATCHING-ON KERNEL REPLACEMENT FOR
  1598. THE 128 AND 64.  ╘HE ARTICLE WILL ALSO DISCUSS FUTURE DIRECTIONS AND DESIGNS
  1599. FOR THE ┴├┼ ENVIRONMENT.  ┴├┼ HAS A NUMBER OF DEFINITE DESIGN ADVANTAGES OVER
  1600. OTHER KERNEL REPLACEMENTS, AND A FEW DISADVANTAGES AS WELL.
  1601.